如何解决“未捕获的错误:断言失败:无法在未定义的对象上调用带有“定义”的设置。”

时间:2019-07-18 16:10:38

标签: javascript ember.js

对于我的实习,我正在制作一个简单的Ember应用程序,在其中我让用户输入要设置为抽认卡标题和抽认卡定义的文本。这些全部作为列表呈现在网页上。

当我为抽认卡输入新标题时,它将更新占位符标题。但是,当我为定义执行此操作时,出现以下错误:

Uncaught Error: Assertion Failed: Cannot call set with 'definition' 
on an undefined object.

我希望通过setCardDefToNewDef操作来更新模型中显示的现有定义中的定义。它应该使用id来查找元素。

// app/controllers/about.js

    init() {
    this._super(...arguments);
    this.set('stashedNewTitlesById', {});
    this.set('stashedNewDefById', {});
  },

 addTitle: false,
 addDef: false,

 actions: {

   stashNewTitle(id, value) {
     this.stashedNewTitlesById[id] = value;
   },

   stashNewDef(idDef, valueDef){
     this.stashedNewDefById[idDef] = valueDef;
   },

   setCardTitleToNewTitle(id) {
     let card = this.model.find(card => id === card.id);
     let newTitle = this.stashedNewTitlesById[id]
     set(card, 'title', newTitle);
     let element = document.getElementById('input-card-new-title-' + id);
     element.value = '';
   },

   setCardDefToNewDef(idDef){
     let cardDef = this.model.find(cardDef => idDef === cardDef.id);
     let newDef = this.stashedNewDefById[idDef]
     set(cardDef, 'definition', newDef);
     let element = document.getElementById('input-card-new-def-' + idDef);
     element.valueDef = '';
   },

// app/routes/about.js

 export default Route.extend({
  model() {
    return [{
    id: 1,
    title: 'What is a route',
    definition: 'a different page on your website'
  }, {
    id: 2,
    title: 'use _super()',
    definition: 'Overriding parent class methods'
  }, {
    id: 4,
    title: 'What is .hbs?',
    definition: 'Handlebards file extension'
  }];
}
});

// app/templates/about.hbs

<ul>
  {{#each this.model as |card index|}}
    <div class="">
      current title: {{card.title}}
      <div class="">
        new title:
        <br>
        <input
          id={{concat "input-card-new-title-" card.id}}
          type="text"
          onchange={{action
            (action "stashNewTitle" card.id)
            value="target.value"
          }}
        />
          <button {{action "setCardTitleToNewTitle" card.id}}>
            update title
          </button>
          <br>
          current definition: {{card.definition}}
          <br>
          new definition:
          <br>
          <input
            id={{concat "input-card-new-def-" cardDef.id}}
            type="text"
            onchange ={{action
            (action "stashNewDef" cardDef.id)
            valueDef="target.valueDef"
        }}
        />
        <button {{action "setCardDefToNewDef" cardDef.id}} >
          update definition
        </button>
      </div>
    </div>
  {{/each}}
</ul>

1 个答案:

答案 0 :(得分:1)

Ola Ericka?谢谢您的提问!另外,感谢您提供源代码,我能够在本地重新创建您的问题并找到了问题?

因此,我将首先显示代码,然后再进行一些解释。首先,我没有更改您的路由文件,因此暂时将其忽略。

这里是控制器:

import Controller from '@ember/controller';
import { set } from '@ember/object';

export default Controller.extend({
  init() {
    this._super(...arguments);
    this.set('stashedNewTitlesById', {});
    this.set('stashedNewDefById', {});
  },

  addTitle: false,
  addDef: false,

  actions: {
    stashNewTitle(id, value) {
      this.stashedNewTitlesById[id] = value;
    },

    stashNewDef(idDef, value) {
      this.stashedNewDefById[idDef] = value;
    },

    setCardTitleToNewTitle(id) {
      let card = this.model.find(card => id === card.id);
      let newTitle = this.stashedNewTitlesById[id]
      set(card, 'title', newTitle);
      let element = document.getElementById('input-card-new-title-' + id);
      element.value = '';
    },

    setCardDefToNewDef(id) {
      let cardDef = this.model.find(card => id === card.id);
      let newDef = this.stashedNewDefById[id]
      set(cardDef, 'definition', newDef);
      let element = document.getElementById('input-card-new-def-' + id);
      element.valueDef = '';
    },
  }
});

这是更新的模板:

<ul>
  {{#each this.model as |card index|}}
    <div class="">
      current title: {{card.title}}
      <div class="">
        new title:
        <br>
        <input
          id={{concat "input-card-new-title-" card.id}}
          type="text"
          onchange={{action
            (action "stashNewTitle" card.id)
            value="target.value"
          }}
        />
          <button {{action "setCardTitleToNewTitle" card.id}}>
            update title
          </button>
          <br>
          current definition: {{card.definition}}
          <br>
          new definition:
          <br>
          <input
            id={{concat "input-card-new-def-" card.id}}
            type="text"
            onchange={{action
              (action "stashNewDef" card.id)
              value="target.value"
            }}
        />
        <button {{action "setCardDefToNewDef" card.id}} >
          update definition
        </button>
      </div>
    </div>
  {{/each}}
</ul>

您将注意到的主要区别是,我为card重用了相同的变量名(而不是cardDef),只是为了保持代码一致而不使自己感到困惑?在这种情况下,这实际上引起了问题,因为您正在设置valueDef="target.valueDef",但实际上无法使用。您需要将其设置为value="target.value",因为这是DOM API所期望的(实际上与Ember无关)。

您可能会注意到代码和我的代码之间还有一些其他差异,但它们可能只是格式上的差异。让我知道您是否还有其他疑问。

现在我们已经解决了严重问题,我想知道您在这里想要实现什么? this所有这些“ stashedNewTitlesById”只是一种阻止您动态更新原始模型的方法吗?如果是这样,那么可能会有一种更简单的方法来进行处理?我很高兴对其进行详细介绍,但是由于我已经回答了您的问题,因此我不确定这是否是正确的论坛……您是否加入了Ember Community Discord了吗?如果您在那里与我联系,我的昵称是@real_ate,我可以帮助您改善此代码示例。