1

Here my class :

function Cart(){
   if (typeof Cart.instance === 'object') {
      return Cart.instance;
   }
   Cart.instance = this;

   //the other method....

   var self = this;
   var items = window.localStorage.getItem(Cart.storageName);
   this.addToCart = function(item){

      if (!(items instanceof Array)) items = [];
      var itemIndex = getItemIndexById(items, item.ID);
      if(typeof(itemIndex) === 'number'){
         items[itemIndex].QuantityInCart++;
      }
      else{
         item.QuantityInCart = 1;
         items.push(item);
      }
      window.localStorage.setItem(Cart.storageName, serializeObjToJSON(items));
   };
}

Cart.storageName = "Cart";

Then I call addToCart function in Home view when I click on addToCart button:

define(["jquery" ,
   "underscore" ,
   "backbone" ,
   "text!templates/Home/homePanel.html",
   "text!templates/Item/itemTemplate.html"
],function($ , _ , Backbone , HomePanel, ItemTemplate){

 var promotionItem = _.template(ItemTemplate);
 var homePanel = _.template(HomePanel);
 var HomeView = Backbone.View.extend({
   initialize: function() {
       myCart1.updateQtyLabel("qtyCart");
       window.localStorage.setItem("User",serializeObjToJSON(customer));
   },
   el: '#webbodycontainer',
   events : {
       "click #addToCart" :  function(){
           myCart1.addToCart(newItem);
           myCart1.updateQtyLabel("qtyCart");
           $("#containernewpromotion").html(promotionItem);
       }
   },
   render : function(){
       this.$el.html(homePanel);
       $("#containernewpromotion").html(promotionItem);
   }
});
 return HomeView;
});

But when I click to the other view, then back to Home view, and click addToCart button again, the item is increasing 2 times (addToCart method executes two time). If I continue to another view and click on the button again , addToCart method executes 3 times.... Always +1 of addToCart method executing when I go to other view and come back to click on add to cart button.

Any idea what could be causing this. Thanks.

Nothing
  • 2,644
  • 11
  • 64
  • 115
  • Check that you're not instantiating a `HomeView` each time you go back to home. – Loamhoof Oct 25 '13 at 08:34
  • @Loamhoof: excuse me, what did you mean here? I just back to `HomeView` on click ``. – Nothing Oct 25 '13 at 09:20
  • Are you removing the View? If not it makes perfect sense since your events are not being unbound. When navigating from view to view, make sure you call view.remove(). This will cleanup events and remove the view from the dom. – TYRONEMICHAEL Oct 25 '13 at 10:14
  • Yes, it's sames each time you come back to HomeView you initialized it again and the events are delegated each time you initialized it. #addToCart button is out of HomeView right? It is not inside its template. If it was inside then you will not have this problem. Try it if you want. Let me see the way you initialize the view. Do you initialize it in the method of the Router? I avoid to initialize it several times saving the instance in a property of my app and if it does not exist y create it: if(!this.home) { this.home=new HomeView(); } this.selectedView = this.home; this.selectedView.show() – ccsakuweb Oct 25 '13 at 10:36
  • @ccsakuweb : Here : `app_router.on('route:home', function( ){ var homeView = new HomeView({}); homeView.render(); });` – Nothing Oct 26 '13 at 00:12
  • @TyroneMichael : Where should I use that `remove()`? – Nothing Oct 26 '13 at 00:14
  • I found http://stackoverflow.com/questions/6569704/destroy-or-remove-a-view-in-backbone-js/11534056#11534056 this question, but don't know where to call the `destroy` method. – Nothing Oct 26 '13 at 06:07

1 Answers1

1

With the information that you told me I think that the problem is that you are creating the view each time you visit the url. I am going to show you what I do when I am going to show a new view or a view that was visible before.

The first thing is that I have the application separated by modules. Each module is a tab and I have all the modules saved in app. So when I want to change the visible view using the url I use a method of app called showSection(SECTION_NAME)

But in your case you will need the next modification:

app_router.on('route:home', function( ){ 
    if(window.currentSection)
        window.currentSection.remove(); //always in your routes destroy the current view
    window.currentSection = new HomeView({}); 
    $("body").append(window.currentSection.$el); 
    window.currentSection.render();
});

Like always is the same in all the routes I use that showSection. And also I have saved some views that are persistent in the time and only hided. So my method app.showSection in app is:

showSection: function (sectionNAME) {
    if(this.currentSection)
        this.currentSection.hide();

    switch(sectionNAME) {
        case "homeNotPersistent":
            if(this.home)
                this.home.remove();
        case "homeNotPersistent":
        case "home": 
            if(!this.home){
               this.home = new HomeView();
               this.$el.append(this.home.$el);
            }
            this.currentSection = this.home;
            break; 
        ...
    }
    this.currentSection.render();
}

I hope it helps. Destroy is the one you told (Destroy or remove a view in Backbone.js). But I use a close method in my project an idea I got from http://lostechies.com/derickbailey/2011/09/15/zombies-run-managing-page-transitions-in-backbone-apps/

I hope I helped you

Edit: I changed destroy for remove from backbonejs >= 1.0 Suggested by @TyroneMichael

Community
  • 1
  • 1
ccsakuweb
  • 789
  • 5
  • 17
  • `app.currentSection.destroy();` where did the `app` come from? – Nothing Oct 27 '13 at 06:19
  • 1
    You need to save an instance of the view you are viewing at the moment to hide it or destroy it after. You can save home or currentsection in a view that contains all the views (that is app for me, it contains a header common between all the views) or you can use window.currentSection instead if you don't like to have a view like this. You can add showSection in window also or in your approuter. Save the instance wherever is better in your project – ccsakuweb Oct 27 '13 at 06:44
  • Hmm... It's so hard to understand, maybe because I'm just a newbie with backbone :/ – Nothing Oct 27 '13 at 06:58
  • 1
    With Backbone >= 1.0, you can use remove opposed to destory? It removes the view from the dom and unbinds events. – TYRONEMICHAEL Oct 27 '13 at 07:05
  • @TyroneMichael You are right, and if I have subviews I would inherit remove and remove each of them. It is nice to have remove now as method of a view. I implemented close before listenTo methods. – ccsakuweb Oct 27 '13 at 14:14
  • @Domo please tell me what you don't understand. I will try to help you. All of as at the begining were newbies. And maybe the problem is mine, I'm spanish and maybe I didn't explain correctly. I have changed thd first code app > window. That must work – ccsakuweb Oct 27 '13 at 14:20
  • @ccsakuweb : When I navigated to another view and back to `HomeView`, the content of `HomeView` is empty. – Nothing Oct 27 '13 at 16:21
  • @Domo can I see your render method? Where are you appending the $el of home? You need to append it to the body or wherever you want. If you want to, before the render add: $("body").append(window.currentSection.$el) or something similar – ccsakuweb Oct 27 '13 at 19:03
  • @ccsakuweb : In my question, I have a `HomeView` block, isn't what you want? – Nothing Oct 28 '13 at 00:40
  • Ok, I need to see where you append home to the html. Something like: $("body").append(home.$el); You need to append the $el of home, each time you create it (new HomeView()). When you create a HomeView a new instance is created, with all its properties new, $el will be new and you must to append it to the body of the web. Maybe you only append the $el the first time, so the next times after remove it, HomeView is empty. I changed app_router.on('route:home', function( ){ and added an example of append homeview to the body. – ccsakuweb Oct 28 '13 at 07:27
  • @ccsakuweb : I have update my view, adding the usage of the template. Hope it is what you want to see. – Nothing Oct 29 '13 at 00:58
  • @Domo ok maybe the problem is el: '#webbodycontainer' , with remove the tag '#webbodycontainer' will be removed and the next time will not exist. I would change el: '#webbodycontainer' by id: 'webbodycontainer' and I will append the $el manually. Like in app_router.on('route:home', function( ){ that I wrote $("body").append(window.currentSection.$el); Replace the selector, instead of "body" write the selector of the parent element of HomeView. – ccsakuweb Oct 29 '13 at 10:37
  • Did you mean, omit `el: 'webbodycontainer'` in `HomeView` and change `$("body").append(window.currentSection.$el);` in router to `$("#webbodycontainer").append(window.currentSection.$el);`? – Nothing Oct 29 '13 at 11:04
  • Yes it's difficult to me because I don't see all the template, files.. I think that changes must work. Try and tell me if something is wrong or if it works. ^^ – ccsakuweb Oct 29 '13 at 11:12
  • When navigating to another view, and come back to `HomeView`, the previous view didn't clear from `HomeView`. – Nothing Oct 30 '13 at 01:47
  • @ccsakuweb : It's working when I change `$("#webbodycontainer").append(window.currentSection.$el);` to `$("#webbodycontainer").html(window.currentSection.$el);`. – Nothing Oct 30 '13 at 02:37
  • Great! Finally it works! But it is strange that append does not work. Other way you can try is currentSection.setElement($("#webbodycontainer")) (there is not need of window... all the time, one time you create it you can access it directly).. Please, could you vote my answer as useful? – ccsakuweb Oct 30 '13 at 07:09
  • `append()` is working, just it append the content in the other view in my `HomeView`, so I changed it to `.html()`. – Nothing Nov 01 '13 at 02:06
  • Did you mean, try `currentSection.setElement()` instead of `$("#webbodycontainer").html(window.currentSection.$el)` ? – Nothing Nov 01 '13 at 02:25
  • I see. Yes I mean that you can use currentSection.setElement($("#webbodycontainer")) instead of $("#webbodycontainer").html(window.currentSection.$el). Whatever you like more – ccsakuweb Nov 04 '13 at 08:14