A
A
Andrii Matenka2016-10-18 14:36:57
backbone.js
Andrii Matenka, 2016-10-18 14:36:57

How to store nested model in localStorage (Backbone + Backbone-relational.js)?

Structure:
1f8849147d8b40a7899ca54c5fe6ef72.jpg
Demo: html.te.ua/builder
The Add Row and Add Column buttons are added for testing purposes only.
Adding the Row model to the collection works great. Saving Row models to localStorage works fine. If you close and open the page, you can see that Row is stored in localStorage. But if you add a Column (in our case, in the Model Row get("id") == "c4" ) you can see that the html is added, but after closing the page, the Column model disappears and is not saved in localStorage joxi.ru/E2p1y9btB5pXvA
Help me figure it out. I am ready to thank you financially for the time and effort spent!

(function ($) {
  window.App = {
    Models: {},
    Collections: {},
    Views: {},
    Router: {}
  };
  // Template
  window.template = function(id) {
    return _.template ( $( id ).html() );
  };
  // RowModel
  App.Models.Row = Backbone.RelationalModel.extend({
    relations: [
      {
        type: Backbone.HasMany,
        key: 'columns',
        relatedModel: 'App.Models.Column',
        includeInJSON: Backbone.Model.prototype.idAttribute,
        collectionType: 'App.Collections.Columns',
        reverseRelation: {
          key: 'columnIn'
        }
      }
    ],
    defaults: {
      columns:[],
      id: null,
      type: "row",
      name: "Row",
      settings: {
      // Some settings
      }
    },
      initialize: function() {
        if ( !this.get("id") ) {
        	this.set({"id": this.cid});
        }
      }
  });
  // ColumnModel
  App.Models.Column = Backbone.RelationalModel.extend({
    relations: [
      {
        type: Backbone.HasMany,
        key: 'modules',
        relatedModel: 'App.Models.Module',
        includeInJSON: Backbone.Model.prototype.idAttribute,
        collectionType: 'App.Collections.Modules',
        reverseRelation: {
          key: 'moduleIn'
        }
      }
    ],
    defaults: {
      modules: [],
      id: null
    },
    initialize: function() {
        if ( !this.get("id") ) {
        	this.set({"id": this.cid});
        }
      }
  });
  // ModuleModel
  App.Models.Module = Backbone.RelationalModel.extend({
    defaults: {
      id: null,
      type: null,
      parent: null,
      name: null,
      tag: null,
      content: null
    },
    initialize: function() {
        if ( !this.get("id") ) {
        	this.set({"id": this.cid});
        }
      }
  });
  // RowsCollection
    App.Collections.Rows = Backbone.Collection.extend({
    	model: App.Models.Row,
    	localStorage: new Backbone.LocalStorage("uni-page-builder")
    });

    // ColumnsCollection
    App.Collections.Columns = Backbone.Collection.extend({
    	model: App.Models.Column
    });

    // ModulesCollection
    App.Collections.Modules = Backbone.Collection.extend({
    	model: App.Models.Module
    });

  // PageBuilderView
  App.Views.PageBuilderView = Backbone.View.extend({
    el: $("#uni-page-builder"),
    initialize: function() {
      var rowsView = new App.Views.RowsView( {collection : App.rows} );
      this.$("#uni-rows").html( rowsView.render().el );
    },
    events: {
      "click #add-row" : "triggerAddRow",
      "click #add-column" : "triggerAddColumn"
    },
    triggerAddRow: function() {
      Backbone.trigger('event-addRow');
    },
    triggerAddColumn: function() {
      Backbone.trigger('event-addColumn');	
    }
  });

  // RowsView
  App.Views.RowsView = Backbone.View.extend({
    className: "uni-builder-content",
    initialize: function() {
      Backbone.on('event-addRow', this.addRow, this);
      Backbone.on('event-addColumn', this.addColumn, this);
      this.collection.on('add', this.renderRow, this );
      //this.collection.on('add:columns', this.fetch(), this);
    },
    render: function() {
      this.collection.each( this.renderRow, this );
      return this;
    },
    renderRow: function(row){
      var rowView = new App.Views.RowView({ model : row });
      this.$el.append( rowView.render().el );
    },
    addRow: function(){
      this.collection.create({
        columns:[],
        id: null,
        type: "row",
        name: "Row",
        settings: {
        // settings
        }
      });
    },
    addColumn: function(){
      this.collection.each( this.createColumn, this );
    },
    createColumn: function(row){
      if (row.get("id") == "c4") {
        column = new App.Models.Column({
          modules: [],
          id: null	
        });
        row.save({columns:column})   	
      }
    }
  });
  
  // RowView
  App.Views.RowView = Backbone.View.extend({
    template: template('#js-uni-row-tmpl'),
    overlayTemplate: template('#js-uni-row-overlay-tmpl'),
    initialize: function() {
      this.model.on('destroy', this.removeRow, this);
    },
    render: function(){
    		var element = this.template(this.model.toJSON());
          	this.setElement(element);
          var columns = this.model.get('columns'),
        columnsView = new App.Views.ColumnsView( {collection : columns} );
    		this.$el.find(".uni-row-content").append(columnsView.render().el);
    		return this;
    },
    events: {
      "mouseenter": "showRowOverlay",
      "mouseleave": "hideRowOverlay",
      "click .js-uni-row-remove": "destroyRow"
    },
    showRowOverlay: function(){
      if (!this.$el.hasClass("uni-block-overlay-active")) {
        var overlay = this.overlayTemplate(this.model.toJSON());
        this.$el.addClass("uni-block-overlay-active").append(overlay);
      }
    },
    hideRowOverlay: function(){
      this.$el.removeClass("uni-block-overlay-active").find(".uni-row-overlay").remove();
    },
    destroyRow: function () {
            this.model.destroy();
    },
    removeRow: function(){
      this.remove();
    }
  });

  // ColumnsView
  App.Views.ColumnsView = Backbone.View.extend({
    className: "uni-col-group",
    initialize: function() {
      this.collection.on('add', this.renderColumn, this );
    },
    render: function() {
      this.collection.each( this.renderColumn, this );
      return this;
    },
    renderColumn: function(column){
      var columnView = new App.Views.ColumnView({ model : column });
      this.$el.append( columnView.render().el );
    }
  });

  // ColumnView
  App.Views.ColumnView = Backbone.View.extend({
    template: template('#js-uni-col-tmpl'),
    render: function(){
    		var element = this.template(this.model.toJSON());
          	this.setElement(element);
    		//this.$el.find(".uni-row-content").append(columnsView.render().el);
    		return this;
    }
  });
  App.rows = new App.Collections.Rows();
  App.rows.fetch().then(function(){
    var UniPageBuilder = new App.Views.PageBuilderView({collection: App.rows});		
  });

} (jQuery));

Answer the question

In order to leave comments, you need to log in

1 answer(s)
A
Anton Bobylev, 2016-10-19
@dpigo

So your Columns models are not stored in localStorage at all, where do they come from after a reboot? See how it is implemented: stackoverflow.com/questions/20408405/backbone-loca...

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question