Aurelia ValueConverter fromView 与 multi-select 混淆
Aurelia ValueConverter fromView confusion with multi-select
我正在尝试在多 select 表单的上下文中使用和理解 Aurelia ValueConverter。我认为很简单的事情,结果对我来说是一个挑战。
我有一个用于创建新交易的表格,该表格通过多 select 输入字段分配了多个类别。我已将表单的输出绑定到 new_deal.categorizations(在数据库中,交易通过分类有类别)。
现在在创建时,通过 'brute force' 方法,我将每个类别 ID 转换为 {category_id: id} 对象,然后再发布到 API。
仅记录 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"}]}
但我认为最好通过 ValueConverter 来完成。
Plunker 是 here 的完整代码,但它基本上是:
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>
有了这个,我得到了
的输出
POST: {"name":"new deal","categorizations":["1","2"]}
在 app.js 的 fromView 中,我认为我可以更改:
return id ? id: null;
到return一个对象而不是一个单独的值:
return id ? {category_id: id} : null
但这会导致此错误:
Uncaught Error: Only null or Array instances can be bound to a multi-select.
经进一步检查,id 似乎以数组形式进入 fromView...
所以我将 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; }
}
}
试图期待一个数组,然后构建一个分类对象数组到 return,但是正如您在 this Plunker 中看到的那样,它会在您单击时丢失 select (虽然调试日志显示正在创建的对象)。
您有一个类别对象数组,每个对象都有一个 name
(字符串)和 id
(数字)。这些将用于填充允许多个 selection:
的 select 元素
export class App {
categories = [
{ id: 1, name: 'test1'},
{ id: 2, name: 'test2'}
];
}
<select multiple size="2">
<option repeat.for="category of categories">${category.name}</option>
</select>
交易对象由 name
(字符串)和 categorizations
组成。分类对象如下所示:{ category_id: 1 }
export class App {
categories = [
{ id: 1, name: 'test1'},
{ id: 2, name: 'test2'}];
deal = {
name: 'new deal',
categorizations: [],
}
}
我们想将 select 元素的值绑定到交易对象的分类,这是一个对象数组。这意味着 select 元素的每个选项都需要有一个对象 "value"。 HTMLOptionElement 的值属性只接受字符串。我们分配给它的任何东西都将被强制转换为一个字符串。我们可以将分类对象存储在可以处理任何类型的特殊 model
属性中。有关这方面的更多信息,请参阅 aurelia docs.
<select multiple size="2">
<option repeat.for="category of categories" model.bind="{ category_id: category.id }">${category.name}</option>
</select>
最后,我们需要将 select 元素的值绑定到交易对象的分类:
<select value.bind="deal.categorizations" multiple size="2">
<option repeat.for="category of categories" model.bind="{ category_id: category.id }">${category.name}</option>
</select>
总而言之,视图和视图模型如下所示:
export class App {
categories = [
{ id: 1, name: 'test1'},
{ id: 2, name: 'test2'}];
deal = {
name: 'new deal',
categorizations: [],
}
createDeal() {
alert(JSON.stringify(this.deal, null, 2));
}
}
<template>
<form submit.delegate="createDeal()">
<label>Name</label>
<input type="text" placeholder="Ex. Buy One Get One Free" value.bind="deal.name">
<label>Categories</label>
<select value.bind="deal.categorizations" multiple size="2">
<option repeat.for="category of categories" model.bind="{ category_id: category.id }">${category.name}</option>
</select>
<button type="submit">Save</button>
</form>
</template>
这是一个有效的 plunker:http://plnkr.co/edit/KO3iFBostdThrHUA0QHY?p=preview
在 Aurelia Gitter 频道 whayes 的帮助下解决了这个问题。所以我希望在 fromView 方法中有一个数组,但我在 ValueConverter 中还需要一个 toView 方法。
export class CategoryToIDValueConverter {
toView(cats){
if (cats){
var ids = [];
cats.forEach(function(categorization){
ids.push(categorization.category_id);
});
return ids;
} else { return null; }
}
fromView(id) {
if(id){
var categorizations = [];
id.forEach(function(cat_id){
categorizations.push({category_id: cat_id})
});
return categorizations;
} else { return null; }
}
}
我也试过,但我最初认为我需要将转换器添加到表单的 select 行和选项行,如下所示:
<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>
但这实际上是不正确的。我只需要将 categoryToID ValueConverter 应用到 select 行,一切都按预期工作。
工作 Plunker 展示了在您单击保存之前,蛮力方法如何不更改模型,而 ValueConverter 会在您更改 selection 时更改它。
决赛app.js
import {LogManager} from 'aurelia-framework';
let logger = LogManager.getLogger('testItems');
export class App {
constructor(){
this.categories = [{id: 1, name: 'test1'}, {id: 2, name: 'test2'}];
this.new_deal = {
name: 'new deal',
categorizations: [],
};
setInterval(() => this.debug = JSON.stringify(this.new_deal, null, 2), 100);
}
create(){
var categorizations = this.new_deal.categorizations;
this.new_deal.categorizations = categorizations.map(function (e) {return {category_id: e}});
alert(JSON.stringify(this.new_deal, null, 2));
}
create2(){
alert(JSON.stringify(this.new_deal, null, 2));
}
}
export class CategoryToIDValueConverter {
toView(cats){
if (cats){
var ids = [];
cats.forEach(function(categorization){
ids.push(categorization.category_id);
});
return ids;
} else { return null; }
}
fromView(id) {
if(id){
var categorizations = [];
id.forEach(function(cat_id){
categorizations.push({category_id: cat_id})
});
return categorizations;
} else { return 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 type="submit" click.delegate="create2()">Save</button>
<!-- debug -->
<pre><code>${debug}</code></pre>
</template>
我正在尝试在多 select 表单的上下文中使用和理解 Aurelia ValueConverter。我认为很简单的事情,结果对我来说是一个挑战。
我有一个用于创建新交易的表格,该表格通过多 select 输入字段分配了多个类别。我已将表单的输出绑定到 new_deal.categorizations(在数据库中,交易通过分类有类别)。
现在在创建时,通过 'brute force' 方法,我将每个类别 ID 转换为 {category_id: id} 对象,然后再发布到 API。
仅记录 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"}]}
但我认为最好通过 ValueConverter 来完成。
Plunker 是 here 的完整代码,但它基本上是:
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>
有了这个,我得到了
的输出POST: {"name":"new deal","categorizations":["1","2"]}
在 app.js 的 fromView 中,我认为我可以更改:
return id ? id: null;
到return一个对象而不是一个单独的值:
return id ? {category_id: id} : null
但这会导致此错误:
Uncaught Error: Only null or Array instances can be bound to a multi-select.
经进一步检查,id 似乎以数组形式进入 fromView...
所以我将 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; }
}
}
试图期待一个数组,然后构建一个分类对象数组到 return,但是正如您在 this Plunker 中看到的那样,它会在您单击时丢失 select (虽然调试日志显示正在创建的对象)。
您有一个类别对象数组,每个对象都有一个 name
(字符串)和 id
(数字)。这些将用于填充允许多个 selection:
export class App {
categories = [
{ id: 1, name: 'test1'},
{ id: 2, name: 'test2'}
];
}
<select multiple size="2">
<option repeat.for="category of categories">${category.name}</option>
</select>
交易对象由 name
(字符串)和 categorizations
组成。分类对象如下所示:{ category_id: 1 }
export class App {
categories = [
{ id: 1, name: 'test1'},
{ id: 2, name: 'test2'}];
deal = {
name: 'new deal',
categorizations: [],
}
}
我们想将 select 元素的值绑定到交易对象的分类,这是一个对象数组。这意味着 select 元素的每个选项都需要有一个对象 "value"。 HTMLOptionElement 的值属性只接受字符串。我们分配给它的任何东西都将被强制转换为一个字符串。我们可以将分类对象存储在可以处理任何类型的特殊 model
属性中。有关这方面的更多信息,请参阅 aurelia docs.
<select multiple size="2">
<option repeat.for="category of categories" model.bind="{ category_id: category.id }">${category.name}</option>
</select>
最后,我们需要将 select 元素的值绑定到交易对象的分类:
<select value.bind="deal.categorizations" multiple size="2">
<option repeat.for="category of categories" model.bind="{ category_id: category.id }">${category.name}</option>
</select>
总而言之,视图和视图模型如下所示:
export class App {
categories = [
{ id: 1, name: 'test1'},
{ id: 2, name: 'test2'}];
deal = {
name: 'new deal',
categorizations: [],
}
createDeal() {
alert(JSON.stringify(this.deal, null, 2));
}
}
<template>
<form submit.delegate="createDeal()">
<label>Name</label>
<input type="text" placeholder="Ex. Buy One Get One Free" value.bind="deal.name">
<label>Categories</label>
<select value.bind="deal.categorizations" multiple size="2">
<option repeat.for="category of categories" model.bind="{ category_id: category.id }">${category.name}</option>
</select>
<button type="submit">Save</button>
</form>
</template>
这是一个有效的 plunker:http://plnkr.co/edit/KO3iFBostdThrHUA0QHY?p=preview
在 Aurelia Gitter 频道 whayes 的帮助下解决了这个问题。所以我希望在 fromView 方法中有一个数组,但我在 ValueConverter 中还需要一个 toView 方法。
export class CategoryToIDValueConverter {
toView(cats){
if (cats){
var ids = [];
cats.forEach(function(categorization){
ids.push(categorization.category_id);
});
return ids;
} else { return null; }
}
fromView(id) {
if(id){
var categorizations = [];
id.forEach(function(cat_id){
categorizations.push({category_id: cat_id})
});
return categorizations;
} else { return null; }
}
}
我也试过,但我最初认为我需要将转换器添加到表单的 select 行和选项行,如下所示:
<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>
但这实际上是不正确的。我只需要将 categoryToID ValueConverter 应用到 select 行,一切都按预期工作。
工作 Plunker 展示了在您单击保存之前,蛮力方法如何不更改模型,而 ValueConverter 会在您更改 selection 时更改它。
决赛app.js
import {LogManager} from 'aurelia-framework';
let logger = LogManager.getLogger('testItems');
export class App {
constructor(){
this.categories = [{id: 1, name: 'test1'}, {id: 2, name: 'test2'}];
this.new_deal = {
name: 'new deal',
categorizations: [],
};
setInterval(() => this.debug = JSON.stringify(this.new_deal, null, 2), 100);
}
create(){
var categorizations = this.new_deal.categorizations;
this.new_deal.categorizations = categorizations.map(function (e) {return {category_id: e}});
alert(JSON.stringify(this.new_deal, null, 2));
}
create2(){
alert(JSON.stringify(this.new_deal, null, 2));
}
}
export class CategoryToIDValueConverter {
toView(cats){
if (cats){
var ids = [];
cats.forEach(function(categorization){
ids.push(categorization.category_id);
});
return ids;
} else { return null; }
}
fromView(id) {
if(id){
var categorizations = [];
id.forEach(function(cat_id){
categorizations.push({category_id: cat_id})
});
return categorizations;
} else { return 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 type="submit" click.delegate="create2()">Save</button>
<!-- debug -->
<pre><code>${debug}</code></pre>
</template>