Использование условного выражения в Ember

Вот моя ссылка на jsfiddle, и я пытаюсь напечатать ниже DropDown сообщение «Выберите вариант B», когда выбран любой вариант, кроме B.

Когда выбран вариант B, мне нужно напечатать идентификатор и имя параметра.

http://jsfiddle.net/fortm/MGX9k/1/

Происходит то, что сообщение «Выберите вариант B» никогда не печатается. Всегда отображаются идентификатор и имя.

Итак, есть некоторая проблема с условным выражением Handlebar -

{{#if App.SearchController.selectedB}}

Где selectedB - это функция, которая возвращает true, когда Option имеет значение B, но, похоже, это не работает.

  selectedB: function() {
    return this.get('selectedName.id') == 2 ;
  }

В качестве побочного вопроса мне нужно было стилизовать раскрывающийся список «Выбрать», поэтому я добавил атрибут «класс». Он получил пользовательский стиль, но в качестве одного из стилей по-прежнему используется ember-select. Можем ли мы удалить ember CSS при добавлении нового собственного стиля?


person fortm    schedule 09.04.2013    source источник
comment
Спасибо MilkyWayJoe и emk, и я хотел бы принять оба ответа. Использование маршрутизатора действительно элегантно, и подсказка ember-data отмечена.   -  person fortm    schedule 09.04.2013
comment
Без проблем! Это была интересная задача по отладке.   -  person emk    schedule 10.04.2013


Ответы (2)


Проблема, которую я здесь вижу, связана не столько с самим условием, сколько с тем, как вы используете свои данные. Несколько вещей:

(Вы можете увидеть больше здесь: http://jsfiddle.net/schawaska/enRhT/)

Если вы хотите, чтобы ваш шаблон реагировал на selectedB, вы должны превратить его в вычисляемое свойство, также указав его зависимости, что в вашем случае является свойством selectedName:

selectedB: function() {
    return this.get('selectedName.id') == 2;
}.property('selectedName') // This is important

Кроме того, я заметил, что в ваших шаблонах вы назначаете свои привязки классу контроллера, а не экземпляру. Рассмотрите возможность изменения вашего приложения, включив в него Router, что позволит вам по-другому устанавливать данные модели.

С помощью механизма маршрутизации контроллер будет назначен вашему маршруту и ​​автоматически привязан к представлению/шаблону, поэтому вместо привязки к App.SearchController.property вы можете сделать это с помощью controller или controller.property:

{{view Ember.Select class="my_custom_class"
    contentBinding="controller.content"
    optionValuePath="content.id"
    optionLabelPath="content.firstName"
    selectionBinding="controller.selectedName"}}

Это потребует еще нескольких изменений.

Настройка маршрутизатора

App.Router.map(function() {
    this.route('search');
});
// this would require that you either create an IndexRoute 
// to redirect from the root to the SearchRoute, or
// change the route path: this.route('search', { path: '/' }); 

возврат данных из функции модели маршрута, а не из контроллера

App.SearchRoute = Em.Route.extend({
    model: function() {
        return [
            {firstName: "Any",  id: 0},
            {firstName: "A",    id: 1},
            {firstName: "B",    id: 2},
            {firstName: "C",    id: 3},
            {firstName: "D",    id: 4},
            {firstName: "E",    id: 5}
        ];
    }
});

Добавление {{outlet}} в шаблон приложения

<script type="text/x-handlebars">
{{outlet}}
</script>

перемещение тела шаблона в определенный шаблон с использованием правильного controller

Теперь, поскольку маршрут предоставляет контроллер и его данные, вы должны иметь возможность использовать ключ controller в своем шаблоне Handlebars, и он будет ссылаться на SearchController (см. ниже).

<script type="text/x-handlebars" data-template-name="search">
    {{view Ember.Select class="my_custom_class"
       contentBinding="controller.content"
       optionValuePath="content.id"
       optionLabelPath="content.firstName"
       selectionBinding="controller.selectedName"}}

    {{#if selectedB}}
      <p>Selected: {{controller.selectedName.firstName}}
      (ID: {{controller.selectedName.id}})</p>
    {{else}}
    <p>Select option B</p>
    {{/if}}    
</script>

Исправление контроллера

App.SearchController = Ember.ArrayController.extend({
  selectedName: null,
  selectedB: function() {
    return this.get('selectedName.id') == 2 ;
  }.property('selectedName')
});

Из-за соглашений об именах ваш маршрут предполагает, что ваше приложение будет иметь SearchController (это точное имя), и именно так он соединяет все вместе. И если ваш контроллер не реализует ArrayController, он взорвется, так как функция вашей модели теперь возвращает ModelArray и не будет привязана к ObjectController (по умолчанию)

person MilkyWayJoe    schedule 09.04.2013

Вот рабочая версия. Вот несколько наиболее важных вещей, которые я изменил:

  1. Я переместил настройки вашего контента в SearchRoute, где ему и место:

    App.SearchRoute = Ember.Route.extend({
      model: function () {
        return [
          Ember.Object.create({firstName: "Any", id: 0}),
    
  2. Я исправил ваш контроллер поиска, чтобы он использовал extend вместо create, и сделал selectedB вычисляемым свойством:

    App.SearchController = Ember.ArrayController.extend({
      selectedName: null,
    
      selectedB: function() {
        // Be careful! If you use Ember Data, the key will be '2', not 2.
        return this.get('selectedName.id') === 2;
      }.property("selectedName.id")
    });
    
  3. Я дал SearchController собственный шаблон и изменил код, чтобы использовать относительные свойства вместо того, чтобы пытаться получить доступ к контроллеру как к глобальному. Я также подключил contentBinding, чтобы он указывал на ваш контроллер поиска, который действует как прокси для вашего фактического контента.

    <script type="text/x-handlebars" data-template-name="search">
    
      {{view Ember.Select class="my_custom_class"
             contentBinding="this"
             optionValuePath="content.id"
             optionLabelPath="content.firstName"
             selectionBinding="selectedName"}}
    

Были и другие незначительные изменения.

person emk    schedule 09.04.2013