How do I leverage Marionette to rerender a nested CompositeView after a child's model is destroyed?

StackOverflow https://stackoverflow.com/questions/23201548

  •  07-07-2023
  •  | 
  •  

質問

I thought Marionette would handle removing the views of destroyed models automatically but it's not working in my situation. I have a CompositeView which displays a collection of movies. Each movie has a list of actors. When I click "Delete Movie" it should delete all the associated actors and update the view with that particular movie which was removed. Currently, my application destroys the models but the view isn't updated. If I refresh the page, the movie and associated actors are gone so I know it's destroying the models, just not the views the moment it is clicked. How can I get Marionette to handle this?

Relevant controller code:

 /* in my list_controller.js */

 MovieApp.module("ActorsApp.List", function(List, MovieApp, Backbone, Marionette, $, _){
  List.Controller = {

    listActors: function(){
      var actors = MovieApp.request("actor:entities");
      var movies = new Backbone.Collection;
      var allMovies= MovieApp.request("movie:entities");

      actors.each(function(actor) {
        movieId = actor.get("movieId");

        if (!movies.get(movieId) ){

          //console.log("Movie not found. Adding to list list.");
          movie = allMovies.get(movieId);

          selectedActors = actors.where({ movieId: movieId });

          //console.log("Selected Actors: ", selectedActors);
          movie.actors=selectedActors;

          movies.add(allMovies.get(movieId));

        }
        else {
          console.log("Movie found in list. Skipping.")

        }

      });

      var moviesListView = new List.Movies({
        collection: movies
      });

      moviesListView.on("itemview:actor:new", function(childView, model){
        MovieApp.ActorsApp.New.Controller.newActor(model);
      });

      moviesListView.on("itemview:itemview:actor:show", function(childView, model){
        MovieApp.ActorsApp.Show.Controller.showActor(model);
      });

      moviesListView.on("itemview:movie:show", function(childView, model){
        MovieApp.MoviesApp.Show.Controller.showMovie(model);
      });

      moviesListView.on("itemview:movie:delete", function(childView, model){

        childView.children.each(function(child){
          child.model.destroy();
        });

        // This removes a model from the moviesListView collection
        this.collection.remove(childView.model);  

        this.render();

      });

      moviesListView.on("itemview:itemview:actor:delete", function(childView, model){
        model.model.destroy();
      });

      moviesListView.on("movie:list", function(){
        MovieApp.MoviesApp.List.Controller.listMovies();
      });

      MovieApp.mainRegion.show(moviesListView);

    }


  }
});

Here is my view code:

List.Movie = Marionette.CompositeView.extend({
    tagName: "li",
    template: "#actor-movie-list-item",
    itemView: List.Actor,
    initialize: function(){

       console.log("Actors: ", this.model.actors);

        actors = this.model.actors;

        this.collection = actors;

        this.collection = new Backbone.Collection(actors);

    },

    events: {
        "click a.js-remove-movie" : "deleteClicked"
    },

    deleteClicked: function(e){
        e.preventDefault();
        e.stopPropagation();
        this.trigger("movie:delete", this.model);
    },

    appendHtml: function(collectionView, itemView, index){
        var container;

        container = this.$('.recipe-list');
        container.append(itemView.el);
    },


    onRender: function() {
        if(_.isUndefined(this.collection)){
            this.$("ul:first").remove();

        }
        console.log("Movie render called.");
    }

  });
役に立ちましたか?

解決

I don't entirely see what you're trying to achieve, however if you want to update the views after destroying a model try this:

recipesListView.on("itemview:movie:delete", function(childView){
    // This removes a model from the recipesListView collection
    this.collection.remove(childView.model);  
});  

This assumes that your recipesListView is either a collection- or a compositeView. Also check: http://lostechies.com/derickbailey/2012/04/05/composite-views-tree-structures-tables-and-more/

I also created a fiddle to demonstrate using a compositeView and deleting an item through events: http://jsfiddle.net/Cardiff/JEx6Y/

If above doesn't help you out, can you explain:
- In the list.view, what's the this.model.actors?
- How are your views structured (nesting of view types)
- How is your data defined in models and collections?

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top