Почему я вижу пустой продукт в products.index?

Вот так выглядит мой products.index:

введите здесь описание изображения

Когда я нажимаю ссылку «Создать продукт». Он отправляет меня к /products/new. Я вижу там форму, но не отправляю ее, вместо этого нажимаю кнопку «Отмена». У меня есть действие в моем контроллере, которое перенаправляет меня на страницу products.index.

  actions: {
    cancel: function() {
      this.transitionToRoute('products.index');

      return false;
    }
  }

В /products я вижу:

введите здесь описание изображения

Что является пустым продуктом... В БД в API нет продуктов. Обновляю страницу, и пустой товар уходит. Что тут происходит?

Полный код:

// app/routes/products/index.js
import Ember from 'ember';

export default Ember.Route.extend({
  model: function() {
    return this.store.find('product');
  }
});

// app/routes/products/new.js
import Ember from 'ember';

export default Ember.Route.extend({
  model: function() {
    return this.store.createRecord('product');
  },
});

// app/controllers/select-addresses/new.js
export default Ember.ObjectController.extend({
  actions: {
    cancel: function() {
      this.transitionToRoute('products.index');

      return false;
    }
  }
});

// app/templates/products/index.hbs
<h1>Products index</h1>

<p>{{#link-to 'products.new'}}Create product{{/link-to}}</p>

<ul>
  {{#each}}
  <li>
    {{#link-to 'products.show' this}}<strong>{{name}}</strong>{{/link-to}}
    <br />Description: {{description}}
    <br />Amount in cents: {{amountInCents}}
    <br />{{link-to 'Edit' 'products.edit' this}} &middot; <a href="#" {{action "delete" this}}>Delete</a>
    <br /><br />
  </li>
  {{/each}}
</ul>

// app/templates/products/new.hbs
<h1>Add a new friend</h1>

<form {{action "save" on="submit"}}>
  <p>
    <label>Name:
      {{input value=name}}
    </label>

    {{#each error in errors.name}}
      <br />{{error.message}}
    {{/each}}
  </p>

  <p>
    <label>Description:
      {{input value=description}}
    </label>

    {{#each error in errors.description}}
      <br />{{error.message}}
    {{/each}}
  </p>

  <p>
    <label>Amount in cents:
      {{input value=amountInCents}}
    </label>

    {{#each error in errors.amountInCents}}
      <br />{{error.message}}
    {{/each}}
  </p>

  <p>
    <label>Status:
      {{input value=status}}
    </label>

    {{#each error in errors.status}}
      <br />{{error.message}}
    {{/each}}
  </p>

  <input type="submit" value="Save"/>
  <button {{action "cancel"}}>Cancel</button>
</form>

{{outlet}}

person Christian Fazzini    schedule 16.01.2015    source источник


Ответы (4)


Используйте ember-data-route, а затем выполните

{{#each product in model}}
  {{#unless product.isNew}}
    {{product.name}}
  {{/unless}}
{{/each}}

Если вы не хотите использовать ember-data-route, вы всегда можете использовать resetController. и сделать model.deleteRecord().

// app/routes/products/new.js
import Ember from 'ember';

export default Ember.Route.extend({
  model: function() {
    return this.store.createRecord('product');
  },

  resetController: function (controller, isExiting) {
    var model = controller.get('model');

    if (isExiting && model.get('isNew')) {
      model.deleteRecord()
    }
  }
});

Более подробную версию см. в том, что ember-data-route делает.

person knownasilya    schedule 16.01.2015

Мое предположение (как не специалист по Ember):

В вашем Ember.Route.extend для модели вы вызываете store.createRecord. Этим вы добавляете пустой товар в магазин. Когда вы отменяете форму, вы не удаляете фиктивный продукт из магазина, поэтому он все еще там, когда вы загружаете индексное представление.

person chiccodoro    schedule 16.01.2015
comment
Это правильно. Один из способов обойти это — использовать github.com/yapplabs/ember-buffered-proxy. где-то. - person Leeft; 16.01.2015
comment
Это здравое предположение. Как вы думаете, где store.createRecord можно определить? - person Christian Fazzini; 16.01.2015
comment
@Leeft, конечно, это довольно распространенная проблема, если это происходит. Есть ли способ заставить это работать нормально без установки внешней библиотеки? Может быть, есть эмберный способ? - person Christian Fazzini; 16.01.2015
comment
Вы бы так подумали, да. Проблема сводится к (а) необходимости получения новой записи из модели, чтобы были установлены значения по умолчанию, и (б) .createRecord() для достижения (а), к сожалению, также отправляет ее в хранилище. Потребуется изменение API ember-data, чтобы вы могли создавать записи, но не отправлять их в хранилище. Вы можете отфильтровать отображаемые записи по состоянию created.uncommitted, хотя я нашел аддон проще и надежнее. Это также помогает, когда существующая запись не изменяется во время редактирования. - person Leeft; 16.01.2015
comment
Не могли бы вы привести пример того, как фильтровать записи по created.uncommitted? - person Christian Fazzini; 16.01.2015
comment
Посмотрите на мой ответ. Возможное решение - person Christian Fazzini; 16.01.2015

Итак, в маршрутах индекса продукта я изменил return this.store.find('product'); на return this.store.find('product', {});.

И проблема ушла! Я не уверен, что это правильный подход, но пока никаких проблем!

// app/routes/products/index.js
import Ember from 'ember';

export default Ember.Route.extend({
  model: function() {
    // Before
    // return this.store.find('product');

    // After
    return this.store.find('product', {});
  }
});

ОБНОВЛЕНИЕ: кажется, что выполнение this.store.unloadAll('product'); перед переходом также работает. Это кажется более естественным решением. Согласно этому запросу на вытягивание https://github.com/emberjs/data/pull/1714

Однако нажатие кнопки «Назад» в браузере по-прежнему отображает пустой продукт.

Итак, в основном:

// app/routes/products/index.js
import Ember from 'ember';

export default Ember.Route.extend({
  model: function() {
    return this.store.find('product');
  }
});

// app/controllers/select-addresses/new.js
export default Ember.ObjectController.extend({
  actions: {
    cancel: function() {
      this.store.unloadAll('product');
      this.transitionToRoute('products.index');

      return false;
    }
  }
});
person Christian Fazzini    schedule 16.01.2015

Вы можете использовать хук маршрута deactivate для удаления новой (не сохраняемой) записи из хранилища.

// app/routes/products/new.js
import Ember from 'ember';

export default Ember.Route.extend({
  model: function() {
    return this.store.createRecord('product');
  },
  deactivate: function () {
    var model = this.modelFor('products.new');
    if (model.get('isNew')) {
      model.destroyRecord();
    }
  }
});

Когда вы переходите с маршрута без сохранения записи с помощью .save(), она уничтожает запись в хранилище и, следовательно, не будет отображаться в шаблоне.

person colinhoernig    schedule 16.01.2015