简体   繁体   中英

Why doesn't changing the Model also change the view in EmberJS?

在此处输入图片说明

I have 4 posts. Each one has a title and an Author. Right now, it is sorted by Author. I would like to click a button (such as Sort By Title) and have the information be sorted by title instead of by author.

So far, I know that I am sorting the authors and titles and the model is being updated. The problem is displaying the updated information in the view. For some reason, I assumed that if I just did this.set('model', newModel) that the new information would display automatically. This is not so.

Here is my code.

practice.hbs

{{outlet}}


<button {{action "sortTitles"}}>Sort by Title</button>
<button {{action "sortAuthors"}}>Sort by Author</button>
{{#each model as |post|}}
    <h2>Title: {{post.title}}</h2>
    <h3>Author: {{post.author}}</h3>
{{/each}}

routes/practice.js

import Ember from 'ember';

export default Ember.Route.extend({
    model() {
        var myArray = [{
            title: "Learning EmberJS",
            author: "Erik Hatchett"
        },{
            title: "Controllers are Dead",
            author: "Frank Treacy"
        },{
            title: "Diddly Doo",
            author: "No I'm Adrian"
        },{
            title: "Yisss",
            author: "Dank Sir"
        }];

        myArray.sort(function(a,b) {
            if (a.author > b.author) {
                console.log(a + " is greater than " + b);
                return 1;
            }
            else {
                console.log(b + " is greater than " + a);
                return -1;
            }
        });

        if ("dat" < "cat") {
            console.log("ayy");
        }

        console.log(myArray[2]);
        return myArray;
    }
});

controllers/practice.js

import Ember from 'ember';

var sortByAuthor = function(a,b) {
            if (a.author > b.author) {
                console.log(a + " is greater than " + b);
                return 1;
            }
            else {
                console.log(b + " is greater than " + a);
                return -1;
            }
        };

var sortByTitle = function(a,b) {
            if (a.title > b.title) {
                console.log(a + " is greater than " + b);
                return 1;
            }
            else {
                console.log(b + " is greater than " + a);
                return -1;
            }
        };



export default Ember.Controller.extend({

    actions: {
        sortAuthors() {
            var myModel = this.get('model');
            console.log(myModel[0].author);
            myModel.sort(sortByAuthor);
            console.log(myModel[0].author);
            this.set('model', myModel);
        },
        sortTitles() {
            var myModel = this.get('model');
            myModel.sort(sortByTitle);
            console.log(myModel[0].title);
            this.set('model', myModel);
        }
    }
});

The information is definitely being sorted and the model is definitely being updated. It just doesn't appear to display the sorted information.

Don't set your model to another value inside your controller. This will not work as this is not how the model binding is setup between the route and the controller. The model must be managed by the route.

Instead, create a controller property called sortedRows which you will update from your controller action. Update your template to loop through sortedRows.

bonus answer

Another, more idiomatic solution is you can set a sort key from your controller action, and have sortedRows be a computed property that fires when sortKey changes, and returns the sorted model.

Some variation of the following should work (I have not tested this):

template.hbs

<button {{action (action 'sortBy' 'title')}}>Sort by Title</button>
<button {{action (action 'sortBy' 'author')}}>Sort by Author</button>

{{#each sortedRows as |row|}}
  <h2>Title: {{row.title}}</h2>
  <h3>Author: {{row.author}}</h3>
{{/each}}

controller.js

export default Ember.Controller.extend({
  sortKey: 'author', // or whatever you want the default sort to be
  sortedRows: Ember.computed('sortKey', function() {
    return this.get('model').sortBy(this.get('sortKey'));
  },

  actions: {
    sortBy(sortKey) {
      this.set('sortKey', sortKey);
    }
  }
});

route.js

export default Ember.Route.extend({
  model() {
    return [...];
  }
});

bonus bonus

You can simplify this further by using Ember.computed.sort, which I will leave as an exercise for the reader.

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