简体   繁体   English

Ember.js没有更新模型

[英]Ember.js not updating model

FINAL UPDATE : Kalman Hazins pointed me in the right direction, the computed property wasn't being called because of the fact that it wasn't rendered onscreen, so it wasn't "necessary" to re-compute it. 最终更新Kalman Hazins指出我正确的方向,计算属性没有被调用,因为它没有在屏幕上呈现,所以重新计算它并不是“必要的”。 I'll include here the final code for the controller: 我将在这里包含控制器的最终代码:

App.QuestionController = Ember.ObjectController.extend({
    isEditing : false,

    resetIsEditing : function() {
        this.set('isEditing', false);
    }.observes('model.id'),

    canEditQuestion : function() {
        return this.get('author.id') === App.currentUser;
    }.property('author.id')
}

UPDATE: a "nice enough" solution has been provided by Raymond Liu below , it doesn't really answer the question "why this is happening", but it's the best I've got so far. 更新:下面的Raymond Liu提供了一个“足够好”的解决方案,它并没有真正回答“为什么会这样”的问题,但这是迄今为止我所能做到的最好的。


I'm learning Ember.js, follwing this book and making some changes. 我正在学习Ember.js,关注本书并做出一些改变。 In my controller I have a property bound to the model, but when I change such model the property is not updated. 在我的控制器中,我具有绑定到模型的属性,但是当我更改此类模型时,该属性不会更新。

This is the controller: 这是控制器:

App.QuestionController = Ember.ObjectController.extend({
    isEditing : false,

    canEditQuestion : function() {
        this.set('isEditing', false);
        return this.get('author.id') === App.currentUser;
    }.property('model')
});

This is the template: 这是模板:

<script type="text/x-handlebars" id="question">
    {{#if isEditing}}
        <!-- edit question form -->
    {{else}}
        <p id="question">{{question}}</p>
        {{#if canEditQuestion}}
            <a href="#" {{action "toggleEditQuestion"}}>Edit question</a>
        {{/if}}
    {{/if}}
</script>

Note that if I move the {{else}} branch content before {{#if isEditing}} it works as expected (but not how I want to). 请注意,如果我将{{else}}分支内容{{#if isEditing}}它将按预期工作(但不是我想要的那样)。

Maybe the fact that question is a nested route matters: 也许question是嵌套路线的事实很重要:

App.Router.map(function() {
    this.resource('questions', function() {
        this.resource('question', { path : '/:question_id' });
    });
});

What I want is that even if I'm already editing a question, if I change model the isEditing property should go back to false and the question form is not shown. 我想要的是,即使我已经在编辑问题,如果更改模型, isEditing属性也应返回false并且不显示问题表单。 Apparently I can solve it if I always render the question, but that's not what I want. 如果我总是提出问题,显然我可以解决它,但这不是我想要的。 What am I missing? 我错过了什么?

EDIT: I'm adding the code for the question and the user model: 编辑:我正在添加questionuser模型的代码:

App.Question = DS.Model.extend({
    title : DS.attr('string'),
    question : DS.attr('string'),
    date : DS.attr('date'),
    author : DS.belongsTo('user', { async : true }),
    answers : DS.hasMany('answer', { async : true }) 
});

App.User = DS.Model.extend({
    fullname : DS.attr('string'),
    email : DS.attr('string'),
    questions : DS.hasMany('question', { async : true })
});

The App.currentUser property is set in the sign_in controller: App.currentUser属性在sign_in控制器中设置:

App.SignInController = Ember.Controller.extend({
    needs : [ 'application' ],

    actions : {
        signIn : function() {
            var email = this.get("email");
            var userToLogin = App.User.FIXTURES.findBy("email", email);

            if(userToLogin === void 0) {
                alert("Wrong email!");
                this.set("email", "");
            }
            else {
                localStorage.currentUser = userToLogin.id;
                App.set('currentUser', userToLogin.id);
            }
        }
    }
});

PS: the complete code for my app is available at https://github.com/goffreder/emberoverflow PS:我的应用程序的完整代码可以在https://github.com/goffreder/emberoverflow上找到

PS2: I managed to get a functioning jsFiddle of my app. PS2:我设法获得了可运行的jsFiddle应用程序。 To reproduce you have to sign in using 'tom@dale.com' email. 要复制,您必须使用“ tom@dale.com”电子邮件登录。 Then, if you click on the first answer, you should see an 'Edit question' link that toggles the question form. 然后,如果您单击第一个答案,您应该会看到一个“编辑问题”链接,可切换问题表格。 Now, with that form opened, if you change question the form will still be availabe, with the new question as content, which is the behaviour I want to avoid. 现在,打开该表单,如果您更改了问题,表单仍然可用,新问题作为内容,这是我想要避免的行为。

@goffredder and @Raymond Liu, the reason for canEditQuestion function/property not firing is as follows. @goffredder和@Raymond Liu, canEditQuestion函数/属性未触发的原因如下。

In Ember.js, the (computed) property evaluation is "magical", but as we all know - "magic" can be expensive. 在Ember.js中,(计算)属性评估是“神奇的”,但众所周知 - “魔术”可能很昂贵。 So, the value of a computed property gets cached, so that "magic" doesn't have to happen all the time and unless something changes that cached value doesn't get recomputed. 因此,将缓存已计算属性的值,这样就不必一直都在发生“魔术”,除非对缓存值进行某些更改不会重新计算。 Not only that, if the property is not being shown on the screen - why bother recomputing it? 不仅如此,如果该属性未显示在屏幕上-为什么还要重新计算它? See this jsbin to see exactly what I am talking about. 看到这个 jsbin,看看我在说什么。 Notice how lazyPropDep never gets updated since lazyDep property is never shown on the screen. 请注意lazyPropDep永远不会更新,因为lazyDep属性永远不会显示在屏幕上。

Now, back to your example. 现在,回到你的例子。 canEditQuestion property is not being rendered to the screen when you are editing the question (since it's in the else block). 编辑问题时, canEditQuestion属性不会呈现在屏幕上(因为它位于else块中)。 Therefore, the canEditQuestion function which resets isEditing to false never gets called. 因此, canEditQuestion其复位功能isEditing从来没有假被调用。

I think what you need is to place the resetting logic into an observer while leaving the other logic in the property as follows: 我认为你需要的是将重置逻辑放入观察者,同时将其他逻辑留在属性中,如下所示:

resetIsEditing : function() {
  this.set('isEditing', false);
}.observes('model.id'),

canEditQuestion : function() {
  return this.get('author.id') === App.currentUser;
}.property('model'),

This way EVERY TIME a new model (with a new model id) gets loaded into the controller (even if the previous model was in edit mode) the observer code will trigger resetting isEditing property to false 这样,每次将新模型(具有新模型ID)加载到控制器中(即使先前模型处于编辑模式),观察者代码也会触发将isEditing属性重置为false

update : I misunderstood your problem. 更新 :我误解了你的问题。 Your want to disable form when go to another question, right? 你想在转到另一个问题时禁用表格,对吧? In your question_routs.js file, add this: 在您的question_routs.js文件中,添加以下内容:

App.QuestionRoute = Ember.Route.extend({
  actions: {
    didTransition: function() {
      this.controller.set('isEditing', false);
      return true; // Bubble the didTransition event
    }
  }
})

These code will set 'isEditing' property to false when you transtion to another question. 当您转换到另一个问题时,这些代码会将'isEditing'属性设置为false。 I noticed that the canEditQuestion function/property will not be called when toggle to another question just if isEiting property is set to true, I think that's the very problem need to be solved. 我注意到,当isEiting属性设置为true时,切换到另一个问题时不会调用canEditQuestion函数/属性,我认为这是需要解决的问题。 And I have no idea why. 我不明白为什么。

It looks as though your computed property depends on two variables, author.id and App.CurrentUser that are not listed in the list of dependent keys. 看来您的计算属性取决于两个变量, author.idApp.CurrentUser未在从属键列表中列出。 Instead you only listed model as a dependent key. 相反,您只将model列为依赖键。 I don't know what the relationship is between author and model , but you should list the actual properties/variables that you need in order to compute your property. 我不知道authormodel之间的关系是什么,但是您应该列出计算属性所需的实际属性/变量。

You can do smthing like: 您可以执行类似的操作:

<script type="text/x-handlebars" id="question">
 {{#unless isEditing}}
    <p id="question">{{question}}</p>
    {{#if canEditQuestion}}
        <a href="#" {{action "toggleEditQuestion"}}>Edit question</a>
    {{/if}}
 {{else}}
    <!-- edit question form -->
 {{/unless}}
</script>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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