7

This is the single page application with vue.js and it does some simple calculation and i am trying to implement this calculation in django but it is not giving me the result I want. Here I made the array in the vue.js dynamic and this is displaying me only the image of the product perfectly but not product.name and product.sell_price and also @click.prevent="addToCart(product)"this function is not working ?? How can i solve it ?

vue.js

   <script src="{% static 'js/vue.js' %}"></script>

   <script type="text/javascript" src="{% static '/js/vue-resource.js' %}"></script>
    <script>

 new Vue({
    el: '#posApp',
    
    data: {
        total: 0,
        discount: 0,
        products: [
            {% for product in products %}
                {
                    "id": {{product.id}},
                    "name": "{{product.name}}",
                    "image": "/media/{{product.image}}",
                    "price": {{product.sell_price}}
                },
              {% endfor %}

        ],
        cart: [],
        search: ""
    },
    methods: {

        addToCart: function(product){

            var found = false;
            for (var i = 0; i < this.cart.length; i++){
                if (this.cart[i].id === product.id){
                    this.cart[i].quantity++;
                    found = true;
                }
            }
            if (!found) {
                this.cart.push({
                    id: product.id,
                    name: product.name,
                    sell_price: product.sell_price,
                    quantity: 1
                });
            }

            this.total += product.sell_price;
        },
        inc: function(item){
            item.quantity++;
            this.total += item.sell_price;
        },
        dec: function(item){
            item.quantity--;
            this.total -= item.sell_price;
            if (item.quantity <= 0){
                var i = this.cart.indexOf(item);
                this.cart.splice(i, 1);
            }
        },
        removeFromCart: function(item){
            this.cart.splice(this.cart.indexOf(item), 1);
            this.total = this.total - (item.sell_price * item.quantity);
        },
        clearCart: function(){
            this.cart = [];
            this.total = 0;
            this.discount = 0;
        },
        payment: function(){
            this.cart = [];
            this.total = 0;
            this.discount = 0;
            alert('Transaction Completed');
        }
    },
    computed: {
        filteredProducts(){
            // var lowerTitle = product.title.toLowerCase();
            return this.products.filter((product) => {
                return product.name.toLowerCase().match(this.search);
            });
        }
    }
});
</script>

html

 <div class="col-md-3" v-for="product in filteredProducts" :key="product.id"> <!-- Inner-Col .// -->
                  <a href="#" @click.prevent="addToCart(product)">
                    <div class="box box-default pos-product-card"> <!-- /.box -->
                      <img class="card-img-top img-responsive" :src="product.image" alt="Card image cap">
                      <div class="box-body"> <!-- /.box-body -->
                        <h4 class="box-title">{{ product.name }}</h4>
                        <!-- <p class="box-text">Some quick example text to build on the card title and make up the bulk of the card's content.</p> -->
                        <button class="btn btn-info"><i class="fas fa-shopping-cart"></i></button>
                      </div> <!-- /.box-body -->
                    </div> <!-- /.box -->
                  </a>
                </div>
{% for category in categories %}
            <div class="tab-pane fade" id="category-{{category.id}}">

                <div class="row"> <!-- Inner-Row .// -->
                    {% for product in category.product_set.all %}
                   <div class="col-md-3" v-for="product in filteredProducts" :key="product.id"> <!-- Inner-Col .// -->
                  <a href="#" @click.prevent="addToCart(product)">
                    <div class="box box-default pos-product-card"> <!-- /.box -->
                      <img class="card-img-top img-responsive" :src="product.image" alt="Card image cap">
                      <div class="box-body"> <!-- /.box-body -->
                        <h4 class="box-title">{{ product.name }}</h4>
                        <!-- <p class="box-text">Some quick example text to build on the card title and make up the bulk of the card's content.</p> -->
                        <button class="btn btn-info"><i class="fas fa-shopping-cart"></i></button>
                      </div> <!-- /.box-body -->
                    </div> <!-- /.box -->
                  </a>
                </div>
                    {% endfor %}
     <table class="table table-hover text-center">
                                  <!-- <thead class="thead-dark"> -->
                                    <tr>
                                      <th>Item</th>
                                      <th>Quantity</th>
                                      <th>Rate</th>
                                      <th>Subtotal</th>
                                      <th>&nbsp;</th>
                                    </tr>
                                  <!-- </thead> -->
                                      <tr v-for="item in cart" :key="{{item.id}}">

                    <td><a href="#">{{ item.name }}</a></td>
                    <td><button class="btn btn-flat btn-xs btn-info p-1 mx-1" @click="inc(item.id)">+</button>[[ item.quantity ]]<button class="btn btn-flat p-1 mx-1 btn-xs btn-info" @click="dec(item.id)">-</button></td>
                    <td><span class="text-muted">{{ item.sell_price }}</span> </td>
                    <td>Rs {{ item.sell_price * item.quantity }}</td>
                    <td><button class="btn btn-xs btn-outline-primary" @click="removeFromCart(item)"><i class="fas fa-trash-alt"></i></button></td>
                  </tr>
                                  </table>
                                </div>
                                <div class="no-item-msg" v-if="cart.length === 0">No items in the cart.</div>
                              </div>
         <table class="table">
                                    <tr>
                      <td>Total Items</td>
                      <td>{{ cart.length }}</td>
                    </tr>
                    <tr>
                      <td>Total Amount</td>
                      <td>{{ total }}</td>
                    </tr>
                    <tr>
                      <td><span class="height-control">Discount (In Amount)</span></td>
                      <td><input type="number" v-model="discount" class="form-control"></td>
                    </tr>
                    <tr class="bg-dark">
                      <td>TO PAY</td>
                      <td>{{ total-discount }}</td>
                    </tr>
1
  • What do you mean by dynamic django variables? How are they "dynamic"? Commented Jun 11, 2019 at 8:50

1 Answer 1

7
+50

There are few points for you to consider:

  1. Seems like you have syntax collision in your html, because Django and Vue.js use same {{ and }} to put variable. But, as Django will process your html before Vue, it will replace

    ``` <h4 class="box-title">{{ product.name }}</h4>```
    

by what it will find in context (Django tepmlate context on server side). You may check source or your page in browser, and probably you will see at that line:

<h4 class="box-title"></h4>

Because it will not find python product variable (and you actually meant js(vue) variable).

Solution: use another Vue delimiters. See https://v2.vuejs.org/v2/api/#delimiters. For example use [[ instead of {{ in Vue: an option to your Vue instance delimiters: ['[[', ']]'], and change that line (and other where you mean Vue variables) to

<h4 class="box-title">[[ product.name ]]</h4>

  1. In Vue data you have not product.sell_price variable, as when you doing
  {% for product in products %}
     {
      "id": {{product.id}},
      "name": "{{product.name}}",
      "image": "/media/{{product.image}}",
      "price": {{product.sell_price}}
      },
  {% endfor %}

you will have product.price, not product.sell_price in Vue. Or you have to change line above to "sell_price": {{product.sell_price}}

  1. Soon you will face troubles with item variable. As you have item in django context, not in Vue data. You should add items to Vue data as you did for products.

  2. In general consider change of your approach from mixing django template and Vue code to:

  • Django delivers data to Vue
  • Vue generating All html and doing your js functions

OR

  • use Django Rest framework(https://www.django-rest-framework.org/) to provide rest API
  • and use Vue only on frontend, load your data from server and put your changes to server by REST calls (using axios for example)

Good luck.

Sign up to request clarification or add additional context in comments.

3 Comments

i solved this issue by adding the delimiters as you suggested now i get some little problem considering the categories filter.The products belonging to the some categories id are not showing properly .Before there was no addtoCart(product) function and it was working now i added this link and now it is not working.Is there any solution for this?Thank you for your help
DRF (django-rest-framework) is not necessary to implement a rest API in Django - you can use ligther (and less intrusive) packages or just do it manually (a rest API its just django views serving json instead of serving html....)
About categories and products again you have confusion in Vue data and Django context. product in django loop will be taken from category.product_set.all but inside that loop Vue will take product from filteredProducts - not from django (not from categories). (Note: I can not see your last changes to source files, if any - better provide github gist or so with your source).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.