Javascript Aurelia ValueConverter fromView与multi-select混淆

Javascript Aurelia ValueConverter fromView与multi-select混淆,javascript,aurelia,Javascript,Aurelia,我试图在多选表单的上下文中使用和理解Aurelia ValueConverter。我本以为是直截了当的事情,结果却成了对我的挑战 我有一个表单来创建一个新政,它通过多选输入字段分配了多个类别。我已经将表单的输出绑定到新的_deal.categorizations中(在数据库中,deals通过categorizations拥有categories) 现在,在创建时,通过一个“暴力”方法,我将在发布到API之前将每个类别ID转换为一个{category_ID:ID}对象 仅记录POST输出的示例:

我试图在多选表单的上下文中使用和理解Aurelia ValueConverter。我本以为是直截了当的事情,结果却成了对我的挑战

我有一个表单来创建一个新政,它通过多选输入字段分配了多个类别。我已经将表单的输出绑定到新的_deal.categorizations中(在数据库中,deals通过categorizations拥有categories)

现在,在创建时,通过一个“暴力”方法,我将在发布到API之前将每个类别ID转换为一个{category_ID:ID}对象

仅记录POST输出的示例:

  create(){
      var categorizations = this.new_deal.categorizations;
      this.new_deal.categorizations = categorizations.map(function (e) {
          return {category_id: e}
      });
      logger.debug ('POST: ', JSON.stringify(this.new_deal));
  }
示例输出:

POST:  {"name":"new deal","categorizations":[{"category_id":"1"},{"category_id":"2"}]}
但我认为这最好通过价值转换器来实现

Plunker有完整的代码,但基本上是:

app.js:

export class App {
  constructor(){
    this.categories = [{id: 1, name: 'test1'}, {id: 2, name: 'test2'}];
    this.new_deal = {
        name:       'new deal',
        categorizations: null,
    };
  }

  create(){
      var categorizations = this.new_deal.categorizations;
      this.new_deal.categorizations = categorizations.map(function (e) {return {category_id: e}});
      logger.debug ('POST: ', JSON.stringify(this.new_deal));
  }

  create2(){
      logger.debug ('POST: ', JSON.stringify(this.new_deal));
  }

}

export class CategoryToIDValueConverter {
    fromView(id) {
        return id ? id: null;
    }
}
和app.html:

<template>
  <h1>Testing ValueConverter</h1>
   <h3 >New Brute Force Deal</h3>
     <form role="form">
       <label>Name</label>
          <input type="text" placeholder="Ex. Buy One Get One Free" value.bind="new_deal.name">
       <label>Categories</label>
          <select value.bind="new_deal.categorizations" multiple size="2">
              <option repeat.for="category of categories" value.bind="category.id">${category.name}</option>
          </select>
       </form>
       <button type="submit" click.delegate="create()">Save</button>

  <h3>New ValueConverter Deal</h3>
    <form role="form">
      <label>Name</label>
          <input type="text" placeholder="Ex. Buy One Get One Free" value.bind="new_deal.name">
      <label>Categories</label>
          <select class="form-control" value.bind="new_deal.categorizations | categoryToID" multiple size="2">
            <option repeat.for="category of categories" value.bind="category.id">${category.name}</option>
          </select>
    </form>
    <button class="btn btn-success" type="submit" click.delegate="create2()">Save</button>
</template>
在app.js中的fromView中,我认为我可以更改:

return id ? id: null;
要返回对象而不是单个值,请执行以下操作:

return id ? {category_id: id} : null
但这导致了这个错误:

Uncaught Error: Only null or Array instances can be bound to a multi-select.
进一步检查后,id看起来像是从视图中以数组的形式出现

因此,我将fromView修改为:

    fromView(id) {
        if(id){
          var categorizations = [];
          id.forEach(function(cat_id){
            categorizations.push({category_id: cat_id})
          });
          logger.debug(categorizations);
          logger.debug(Object.prototype.toString.call(categorizations));
          return categorizations;
        } else { return null; }
    }
}

尝试期望一个数组,然后构建一个要返回的分类对象数组,但正如您在中所看到的,它会在您单击时丢失选择(尽管调试日志显示正在创建的对象)。

您有一个类别对象数组,每个类别对象都有一个
名称
(字符串)和
id
(数字)。这些将用于填充允许多个选择的选择元素:

导出类应用程序{
类别=[
{id:1,名称:'test1'},
{id:2,名称:'test2'}
];
}

${category.name}
交易对象由
名称
(字符串)和
分类
组成。分类对象如下所示:
{category\u id:1}

导出类应用程序{
类别=[
{id:1,名称:'test1'},
{id:2,名称:'test2'}];
交易={
名称:“新政”,
分类:[],
}
}
我们希望将select元素的值绑定到deal对象的分类中,deal对象的分类是一个对象数组。这意味着每个select元素的选项都需要有一个对象“值”。HTMLOptionElement的value属性仅接受字符串。我们分配给它的任何内容都将被强制为字符串。我们可以将分类对象存储在一个特殊的
模型
属性中,该属性可以处理任何类型。有关这方面的更多信息,请参阅


${category.name}
最后,我们需要将select元素的值绑定到deal对象的分类:


${category.name}
总之,视图和视图模型如下所示:

导出类应用程序{
类别=[
{id:1,名称:'test1'},
{id:2,名称:'test2'}];
交易={
名称:“新政”,
分类:[],
}
createDeal(){
警报(JSON.stringify(this.deal,null,2));
}
}

名称
类别
${category.name}
拯救

这里有一个正在工作的plunker:

在Aurelia Gitter频道的帮助下解决了这个问题。因此,我希望fromView方法中有一个数组,但我也需要ValueConverter中有一个toView方法

导出类CategoryToIDValueConverter{
托维尤(猫){
如果(猫){
var-id=[];
cats.forEach(功能(分类){
id.push(categorization.category\u id);
});
返回ID;
}else{return null;}
}
fromView(id){
如果(id){
var分类=[];
id.forEach(功能(类别id){
push({category\u id:cat\u id})
});
返回分类;
}else{return null;}
}
}
我也尝试过,但我最初认为需要将转换器添加到表单的选择行和选项行,如下所示:


${category.name}
但这实际上是不正确的。我只需要将categoryToID ValueConverter应用于select行,一切都按预期进行

显示暴力方法如何在单击“保存”之前不会更改模型,并且ValueConverter会在您更改选择时随时更改模型

最终app.js

从'aurelia framework'导入{LogManager};
让logger=LogManager.getLogger('testItems');
导出类应用程序{
构造函数(){
this.categories=[{id:1,名称:'test1'},{id:2,名称:'test2'}];
这项新交易={
名称:“新政”,
分类:[],
};
setInterval(()=>this.debug=JSON.stringify(this.new_deal,null,2),100);
}
创建(){
var分类=此.new_deal.categorizations;
this.new_deal.categorizations=categorizations.map(函数(e){return{category_id:e});
警报(JSON.stringify(this.new_deal,null,2));
}
create2(){
警报(JSON.stringify(this.new_deal,null,2));
}
}
导出类CategoryToIDValueConverter{
托维尤(猫){
如果(猫){
var-id=[];
cats.forEach(功能(分类){
id.push(categorization.category\u id);
});
返回ID;
}else{return null;}
}
fromView(id){
如果(id){
var分类=[];
id.forEach(功能(类别id){
push({category\u id:cat\u id})
});
返回分类;
}else{return null;}
}
}
Final app.html


测试值转换器
新暴力交易
名称
类别
${category.name}
拯救
新价值转换器交易
名称
类别
${category.name}
拯救

我已经把它用到了您描述的地方
    fromView(id) {
        if(id){
          var categorizations = [];
          id.forEach(function(cat_id){
            categorizations.push({category_id: cat_id})
          });
          logger.debug(categorizations);
          logger.debug(Object.prototype.toString.call(categorizations));
          return categorizations;
        } else { return null; }
    }
}