简体   繁体   中英

After using jQuery UI to sort an Ember.js item, using Ember Data's model.deleteRecord() doesn't work

I'm using jQuery UI Sortable with Ember.js to sort a list of items, and it seems to work great, until I go to delete one of the Ember Data records. The model is deleted properly, but the UI doesn't update to reflect that. If you delete the last record, an Index Out of Range error is thrown. If you delete a middle record, the one after it is removed from the DOM. If you delete the first record, it removes the first and second one from the DOM. What gives?

Given the following Handlebars:

<script type="text/x-handlebars" data-template-name="application">
    <h1>Ember Data + jQueryUI Sortable Problems</h1>
    {{outlet}}
    Try sorting and then deleting something. The model is deleted properly, but the DOM does not reflect that. Sometimes it stays in the DOM, sometimes the wrong one is deleted, and sometimes both the right and a wrong one is deleted.
</script>
<script type="text/x-handlebars" data-template-name="index">
    {{#each model}}
        {{render 'formField' this}}
    {{/each}}
</script>
<script type="text/x-handlebars" data-template-name="formField">
    <div class="form-field" {{bind-attr data-id=id}}>
        <span class="delete" {{action 'delete'}}>X</span>
        {{name}} ({{displayOrder}})
        <span class="handle">#</span>
    </div>
</script>

And the following JavaScript:

App.IndexController = Ember.ArrayController.extend({
    sortProperties: ['displayOrder'], // Force sort by displayOrder, not ID
    updatePositions : function(positionData){
          this.propertyWillChange('content'); // Manually notify Ember
          this.get('content').forEach(function(formField) {
              var key = formField.get('id');
              formField.set('displayOrder', positionData[key] + 1);
          });
          this.propertyDidChange('content'); // Manually notify Ember
      }
    });

App.IndexView = Ember.View.extend({
    handleSort: function(event,ui){
        var positionData = {};
        this.$(".form-field").each(function(index, element){
            // Get model ID from bind-attr in template
            var key = $(element).data('id');
            positionData[key] = index;
        });
        this.get('controller').updatePositions(positionData);
        // Delay recreating the sortable
        Ember.run.next(function(){ this.makeSortable(); }.bind(this));
    },
    makeSortable: Ember.on('didInsertElement', function(){
        try {
            this.$().sortable("destroy");
        } catch(err){ 
            window.console.warn('No sortable to destroy', err);
        }
        finally {
            this.$().sortable({
                handle: '.handle',
                axis: 'y',
                update: this.handleSort.bind(this)
            });
        }
    })
});

App.FormFieldController = Ember.ObjectController.extend({
    actions: {
        'delete': function() {
            window.console.log('deleting record', this.get('name'));
            this.get('model').deleteRecord();
        }
    }
});

Here's a fiddle .

The trick is in your use of sortProperties and {{#each model}} or {{#each content}} . The sortProperties method does not actually arrange content or model , it arranges arrangedContent . By changing it to {{#each arrangedContent}} , your problems disappear because the DOM arrangement will stay in sync with your model arrangement.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM