2014-09-10 1 views
0

Я изучаю ember, воссоздавая TodoMVC в EmberCli. Ive воссоздал все функциональные возможности, но я столкнулся с проблемой, и я надеялся, что кто-то может пролить свет на ситуацию.Наблюдение за изменениями в ItemController в контроллере массива

Кажется, что мой Todos ArrayController будет наблюдать и запускать функции, когда свойства в моей модели меняются, но не когда меняются значения в моем объекте ObjectController.

Я переехал isEditing в Model, так что, когда я звоню editTodocanToggle пожаров. Но я бы предпочел сохранить это значение в моем контроллере, а не в модели.

Я установил тест с помощью propTest boolean. при нажатии кнопки я запускаю propToggle, но todoPropToggle не отвечает на изменение. Единственный раз, когда он когда-либо срабатывает, - это инициализация.

Любое понимание было бы очень полезно.

TODOS CONTROLLER

import Ember from 'ember'; 
export default Ember.ArrayController.extend({ 
actions: { 
    createTodo: function() { 
    var title = this.get('newTitle'); 
    if (!title.trim()) { 
     return; 
    } 
    var todo = this.store.createRecord('todo', { 
     title: title, 
     isCompleted: false, 
     isEditing:false 
    }); 

    this.set('newTitle', ''); 
    todo.save(); 
    } 
    }, 

    canToggle: function() { 
    var isEditing = this.isAny('isEditing'); 
    return this.get('length') && !isEditing; 
    }.property('length','@each.isEditing'), 

    todoPropToggle: function() { 
    var hasPropTest = this.isAny('propTest'); 
    return hasPropTest; 
    }.property('@each.propTest') 
}); 

TODO CONTROLLER

import Ember from 'ember'; 

export default Ember.ObjectController.extend({ 

    actions: { 
    editTodo: function() { 
     var todo = this.get('model'); 
     todo.set('isEditing', true); 
    }, 

    removeTodo: function() { 
     var todo = this.get('model'); 
     todo.deleteRecord(); 
     todo.save(); 
    }, 

    acceptChanges: function() { 
     var todo = this.get('model'); 
     todo.set('isEditing', false); 
     if (Ember.isEmpty(this.get('model.title'))) { 
     this.send('removeTodo'); 
     } 
     else { 
     this.get('model').save(); 
     } 
    }, 

    propToggle:function(){ 
     this.set('propTest',!this.get('propTest')); 
    } 
    }, 

    propTest:true, 

    isCompleted: function(key, value) { 
    var model = this.get('model'); 
    if (value === undefined) { 
     return model.get('isCompleted'); 
    } 
    else { 
     model.set('isCompleted', value); 
     model.save(); 
     return value; 
    } 
    }.property('model.isCompleted') 
}); 

ответ

1

Как насчет альтернативного подхода? Мы могли бы переключать «canToggle» в arrayController непосредственно из контроллера объекта либо с помощью parentController, либо с учетом потребностей. Избегает необходимости наблюдать за всеми элементами контроля, которые также должны быть более эффективными.

TODOS CONTROLLER:

import Ember from 'ember'; 
export default 
Ember.ArrayController.extend({ 
    /** 
    * references the todo model that is currently being edited 
    */ 
    editingTodo: null, 
    canToggle: Ember.computed.notEmpty('editingTodo'), 

    actions: { 
     createTodo: function() { 
      var title = this.get('newTitle'); 
      if (!title.trim()) { 
       return; 
      } 
      var todo = this.store.createRecord('todo', { 
       title: title, 
       isCompleted: false, 
       isEditing: false 
      }); 

      this.set('newTitle', ''); 
      todo.save(); 
     } 
    } 
}); 

TODO CONTROLLER

import Ember from 'ember'; 

export default 
Ember.ObjectController.extend({ 

    needs:['todos'] 
    todos : Ember.computed.alias('controllers.todos'), 

    actions: { 
     editTodo: function() { 
      this.set('todos.editingTodo', this.get('model')); 
     }, 

     removeTodo: function() { 
      var todo = this.get('model'); 
      if (this.get('todos.editingTodo') === todo) { 
       this.set('todos.editingTodo', null); 
      } 
      todo.deleteRecord(); 
      todo.save(); 
     }, 

     acceptChanges: function() { 
      this.set('todos.editingTodo', null); 
      if (Ember.isEmpty(this.get('model.title'))) { 
       this.send('removeTodo'); 
      } 
      else { 
       this.get('model').save(); 
      } 
     } 
    }, 

    isCompleted: function (key, value) { 
     var model = this.get('model'); 
     if (value === undefined) { 
      return model.get('isCompleted'); 
     } 
     else { 
      model.set('isCompleted', value); 
      model.save(); 
      return value; 
     } 
    }.property('model.isCompleted') 
}); 

Я не проверял, но я надеюсь, что вы получите тэк решения я предлагаю.

+0

Это похоже на работу, но это действительно конец для того, что я хотел бы делать. Это действительно лучшая практика для такого типа функциональности? Основываясь на коде в примере TodoMVC, я ожидал более чистого пути. – Caranicas

+0

Я думаю, что другое решение, которое может быть лучше, - это решение на основе маршрута. Таким образом, на вашем маршруте todo используйте активировать и деактивировать крючки, чтобы установить свойство canToggle в контроллере todos. –

+0

Означает ли это, что нет никакого способа наблюдать свойство объектных контроллеров от контроллера массива? – Caranicas

1

propTest В этом сценарии здесь выглядит как вычисленное свойство, а не наблюдаемое. (edit: не то, что вычисленные свойства не имеют базовых наблюдаемых, которые их приводят, но они различны в использовании, достаточном для того, чтобы я их разделял). Он срабатывает, когда запускается базовый propTest, но если изменений нет, ember будет no-op, который находится в цикле запуска. Если вы предпочли бы это быть необработанным, используйте синтаксис observes(). @each будет работать здесь, но мне нравится быть явным и иметь наблюдаемое обновление, что ему нужно, а не использовать вычислимое свойство, если только мне не нужен прямой доступ к этому свойству для привязки в шаблоне.

«Только стрельба по исполнению» проистекает из первоначальных привязок из созданного созданного свойства. Если после этого он не срабатывает, базовые привязки, которые вы используете для вычисленного свойства @each.propTest, должны быть неверными, иначе это действительно срабатывало.

Я думаю, вы также можете быть смущены цели ObjectController. Ember.Object может выполнять всю наблюдаемую бизнес-деятельность, которую может иметь контроллер, не имея свойства «model» или «content», поддерживающего его. Похоже, вы можете пойти с прямолинейным объектом, а не с контроллером здесь для todo, поскольку у ember действительно нет типа модели. Затем я помещал объекты как часть содержимого ArrayController, после чего @each мог бы выполнять итерацию на них, как вы ожидали.

ObjectController находится на том же уровне использования, что и ArrayController. Конечно, вы можете их разложить, как вы это делали, но мое здравомыслящее чувство покалывает, что это неправильно делать с учетом приложения. Вероятно, вам не нужен контроллер поддержки для каждого todo-объекта, вам просто нужен сам объект todo.

Смежные вопросы