Amit Bondwal
Amit Bondwal

Reputation: 161

Cannot read property 'bind' of undefined

I am trying to create a cart, In this I am trying to call an ajax post function, by putting an add button in cart with item. In my below code in cart function, if I remove this line of onclinck function

onClick={ this.createNeworder.bind( this, this.orderid, this.item.product_code)}> Add </a> </span> , 

or add just a simple button, it show the item and button in cart. But if I add this line of code then it gives the error Cannot read property 'bind' of undefined and don't add any item in cart. I have used same onclick function in other page code and It is working but I don't know why it is not working here.

var orderid = document.getElementById('bizorderid').innerHTML;
console.log(orderid);

function testAjax() {
return $.ajax({
            type: 'GET',
            url: "/restaurant/menu/list/100/1",
            headers: {
                                    Accept : "application/json",
                                                 "Content-Type":   "application/json"
                    },
            async : false
            }).done( function(json) {
                    //tata = json;

//                      console.log(json);
                    return json;
            }).responseText;

            }

  var dt = testAjax();
  var productsCollection = JSON.parse(dt);
  //var promise = $.parseJSON(pt);
  console.log(productsCollection)

/** @jsx React.DOM */

var Product = React.createClass({
getInitialState: function() {
  return {
    added: false
  };
},

addToCart: function(e) {
  if(!this.state.added) {
    // add
    $.publish('cart.added', this.props.data);
  }
  else {
    // remove
    $.publish('cart.removed', this.props.data.id);
  }

  this.setState({
    added: !this.state.added
  });
},

render: function() {
    // assign to props
    var data = this.props.data;

return (
      <div className="card">
        <div className="title">
          <h3><a>{data.product_name}</a></h3> </div>
          <div className="content">Price :{data.price}  <br />category : {data.groupid} <br />
                    Units: {data.unit} <br /> Code : {data.product_code} <br />
            <button className={this.state.added ? 'button  success' : 'button small radius'} onClick={this.addToCart}>
              {this.state.added ? 'Remove' : 'Add to cart'}
            </button>
        </div>
            </div>
          );
      }
  });


  /** @jsx React.DOM */

  var ProductsList = React.createClass({
      render: function() {

          var products = this.props.data.map(function(product) {
              return (
                <li key={product.product_code}>
                  <Product data={product} />
                </li>
              )
          });

          return (
            <ul className="clearfix">
              {products}
            </ul>
          );
      }
  });

  var Cart = React.createClass({

  createNeworder: function(orderid, product_code) {
                                      //var tbn = this.iid;
                                     // var tbn = iid;
                                var o_id = orderid;
                                console.log(o_id);
                                var p_code = product_code;
                                var unit = 1;
                                      $.ajax({
                                                url: '/restaurant/order/product/'+o_id+'/'+p_code+'/'+unit,
                                                type: 'POST',
                                                headers: {
                                                            // Accept : "application/json",
                                                             "Content-Type": "application/json"
                                                          },

                                                success: function(data) {
  //                                              console.log(data.orderid);
                                                  var orderid = data.orderid;
                                                  console.log(orderid);

                                                //  window.location = '/diner/orderdiner/'+orderid;

                                                  this.setState({data: data});
                                                        }.bind(this),
                                                error: function(xhr, status, err) {
                                       //   console.error(this.props.url, status, err.toString());
                                                        }.bind(this)
                                                      });
                                    },


  getInitialState: function() {
        // also subscribe to product events here
        $.subscribe('cart.added', this.addItem);
        $.subscribe('cart.removed', this.removeItem);

        return {
          items: [],
          total: 0,
          currency: 'EUR'
        };
      },

      addItem: function(e, item) {
        this.state.items.push(item);
        this.forceUpdate();

        this.countTotal();
      },

      removeItem: function(e, itemId) {
        var itemIndexInArray;

        this.state.items.some(function(item, index) {
          if(item.id === itemId) {
            itemIndexInArray = index;
            return true;
          }
        });

        this.state.items.splice(itemIndexInArray, 1);
        this.forceUpdate();

        this.countTotal();
      },

   countTotal: function() {
        var total = 0;

        this.state.items.forEach(function(item, index) {
          total += item.price;
        });

        this.setState({
          total: total
        })
      },

      render: function() {

          var items = this.state.items.map(function(item) {
            //      var pro_code = {item.product_code} ;
    //              console.log(pro_code);
              return (
                <li key={item.id} className="cart-item">
                  <span className="cart-item__name">{item.product_name}</span>
                  <span className="cart-item__price">{item.price} {item.currency}</span>
                  <span hidden className="cart-item__price">{item.product_code} {item.currency}</span>
            <span > <a onClick={ this.createNeworder.bind( this, this.orderid, this.item.product_code)} > Add </a> </span>
                </li>
              )
          });

          var body = (
            <ul>
              {items}
            </ul>
          );

          var empty = <div className="alert alert-info">Cart is empty</div>;

            return (
            <div className="panel panel-default">
              <div className="panel-body">
                {items.length > 0 ? body : empty}
              </div>
            </div>
          );
      }
  });


  React.render(<ProductsList data={productsCollection} />, document.getElementById('tabmenu'));
        React.render(<Cart />, document.getElementById('cart'));

Upvotes: 3

Views: 27991

Answers (1)

sujay
sujay

Reputation: 681

React lets you pass data from the child component back up to its parent. We do this in the parent's render method by passing a new callback (some custom callback) into the child, binding it to the child's (click/any other) event. Whenever the event is triggered, the callback will be invoked.

I see that you are associating the callback for an onclick and hence you need to wrap the whole items array which is the result of map by doing something like

this.state.items.map(function(item) {
return (
   // binding of child's event
)}.bind(this);

where this will be instance of your cart class

source: React Documentation

Upvotes: 4

Related Questions