我们希望(重新)构建一个网络应用程序。我们想使它同构,因此服务器可以呈现相同的模板,但是存在javascript状态模型并处理更新。我认为ractivejs和小胡子/把手是一个相当有前途的选择。
然而,我遇到了一个问题。我们的大多数网站主要是具有一些扩展功能的表单。我们有许多字段,但是可能有很多行要呈现每个字段。一些字段具有依赖字段:例如,作为国家列表的字段可以具有依赖字段状态:对于某些国家/地区,状态字段不存在,而对于其他字段,它具有,但根据国家/地区具有不同的可能值
例如,我们可能有以下数据
{
"data": [{
"firstName": "Joe",
"lastName": "Bloggs",
"travelDocument": "PASS BOOK",
"issueCountry": "US",
"issueState": "CA",
"iterator_row_num": "0"
},
{
"firstName": "Anne",
"lastName": "Other",
"travelDocument": "ID",
"expiryDate": "2021-01-02",
"issueDate": "1921-03-04",
"iterator_row_num": "1"
}],
"fields": {
"firstName": {
"type": "text",
"isList": false,
"isDate": false
},
"lastName": {
"type": "text",
"isList": false,
"isDate": false
},
"travelDocument": {
"type": "list",
"possibleValues": [{
"name": "Passport",
"dependentFields": [{
"name": "Issue Country",
"type": "list",
"possibleValues": [{
"name": "\u00c5land",
"value": "AX"
},
{
"name": "Finland",
"value": "FI"
},
{
"name": "Sweden",
"value": "SV"
},
{
"name": "United States",
"dependentFields": [{
"name": "Issue State",
"type": "list",
"possibleValues": [{
"name": "Alaska",
"value": "AL"
},
{
"name": "California",
"value": "CA"
},
{
"name": "New York",
"value": "NY"
}],
"isList": true,
"isDate": false,
"fieldName": "issueState"
}],
"value": "US"
}],
"isList": true,
"isDate": false,
"fieldName": "issueCountry"
},
{
"name": "Expiry Date",
"type": "date",
"isList": false,
"isDate": true,
"fieldName": "expiryDate"
}],
"value": "PASS BOOK"
},
{
"name": "ID Card",
"dependentFields": [{
"name": "Expiry Date",
"type": "date",
"isList": false,
"isDate": true,
"fieldName": "expiryDate"
},
{
"name": "Issue Date",
"type": "date",
"isList": false,
"isDate": true,
"fieldName": "issueDate"
}],
"value": "ID"
}],
"isList": true,
"isDate": false
}
}
}
我在列表类型字段的<select>
元素中遇到了一些问题。我想在模板中做的事情是:
{{#data}}
<input type="text" value="{firstName}" name="firstname[{{iterator_row_num}}]" />
<input type="text" value="{lastName}" name="lastname[{{iterator_row_num}}]" />
<select name="travelDocument[{{iterator_row_num}}]">
{{#fields.travelDocument.possibleValues}}
<option value="{{value}}"
{{#if value == travelDocument }}
selected
{{/if}}
>{{name}}</option>
{{/fields.travelDocument.possibleValues}}
</select>
{{#fields.travelDocument.possibleValues}}
{{#if value == travelDocument}}
dependent fields here
{{/if}}
{{/fields.travelDocument.possibleValues}}
{{/data}}
但如果进行比较,胡子不允许。我尝试在我的数据模型中添加一个内部计数器,并在每个循环开始时添加一个递增函数。此函数基本上遍历了字段,并根据当前数据为每个可能的值添加/更新了布尔isCurrent
属性。这适用于PHP,但后来我不得不在js层重复我的增量函数。我无法让它发挥作用。它似乎根据依赖字段的第一行设置所有行
我的模板看起来像是:
{{initLoop}}
{{#data}}
{{advanceLoop}}
<input type="text" value="{firstName}" name="firstname[{{iterator_row_num}}]" />
<input type="text" value="{lastName}" name="lastname[{{iterator_row_num}}]" />
<select name="travelDocument[{{iterator_row_num}}]">
{{#fields.travelDocument.possibleValues}}
<option value="{{value}}"
{{#isCurrent }}
selected
{{/isCurrent}}
>{{name}}</option>
{{/fields.travelDocument.possibleValues}}
</select>
{{#fields.travelDocument.possibleValues}}
{{#isCurrent}}
{{#dependentFields}}
dependent fields here
{{/dependentFields}}
{{/isCurrent}}
{{/fields.travelDocument.possibleValues}}
{{/data}}
我的数据模型上有indexN
(整数)和fixedIndex
(布尔)属性。 initLoop
函数只是将indexN
设置为-1。
然后我的功能有点像:
data._set_current_name = function() {
this._currentName = false;
if( this.data[this.indexN] !== undefined ) {
this._currentName = this.data[this.indexN];
}
for( var field_id in this.fields ) {
this._update_field_values(field_id, this.fields[field_id]);
}
};
data._get_current_val = function(field_id) {
var currentVal = '';
if( false !== this._currentName && this._currentName[field_id] !== undefined ) {
currentVal = this._currentName[field_id];
}
return currentVal;
};
data._update_field_values = function(field_id, field) {
var currentVal = this._get_current_val(field_id);
switch( field.type ) {
case 'list':
if( field.possibleValues ) {
for( var posVal_i in field.possibleValues ) {
var posVal = field.possibleValues[posVal_i];
posVal.isCurrent = ( posVal.value === currentVal );
if( posVal.dependentFields ) {
for( var depField_i in posVal.dependentFields ) {
var depField = field.possibleValues[posVal_i].dependentFields[depField_i];
this._update_field_values(depField.fieldName, field.possibleValues[posVal_i].dependentFields[depField_i]);
}
}
}
}
break;
default:
field.currentValue = currentVal;
break;
}
};
data.advanceNameLoop = function() {
if( !this._fixedCounters ) {
++this.indexN;
}
this._set_current_name();
return '';
};
我们还希望它在您更改“父”字段的值时自动更新显示哪些相关字段。尝试在ractive一侧添加一个观察者,它设置当前行的索引,但它不能一直保持。此外,更改选择似乎甚至没有触发它,而更改文本字段呢? (与观察者一起在特定选择和.*
上尝试获取所有字段)。
我的观察者看起来像:
names.observe('data.*.*', function(newValue, oldValue, keyPath){
var pathParts = keyPath.split('.');
this.viewmodel.data.setNameIndexes(pathParts[2]);
});
setNameIndexes
是:
data.setNameIndexes = function(nameIndex) {
this.indexN= nameIndex;
this._fixedCounters = true;
};
我是否沿着正确的线路来到这里?如何处理多个字段的数据数组。鉴于某些字段(例如国家/地区)可能具有许多可能的值,我真的希望避免为每个数据行单独复制整个字段。如果不是在胡子/ ractive
中处理选择的更好方法,那似乎很奇怪(注意:这是我所拥有的简化版本:我们对数据进行了分类,因此我有一个双索引(类别,然后是名称)和更多字段。由于这个原因,可能会出现一些小错误。以上)
答案 0 :(得分:0)
您无需在ractive上手动设置标签上的选定属性。请参阅此处<select>
元素中的部分:http://docs.ractivejs.org/latest/two-way-binding
在顶部简要介绍一下你的JSON,以及你要做的事情,这应该是这样做的:
{{#each data}}
...
<select name="travelDocument{{iterator_row_num}}" value="{{travelDocument}}">
{{#each possibleValues}}
<option value="{{value}}">{{name}}</option>
{{/each}}
</select>
{{/each}}
这将使data [i] .travelDocument与其选择框值保持同步。
对于问题的第二部分,根据所选的travelDocument显示相关字段...
{{#each fields.travelDocument.possibleValues}}
{{#if value == travelDocument}}
{{#each dependentFields}}
I am a {{type}} named {{name}} <!-- you get the point -->
{{/each}}
{{/if}}
{{/each}}
有很多方法可以做到,但这应该让你开始。