如何在ractivejs中明智地处理选择?

时间:2016-06-08 10:51:36

标签: php mustache ractivejs mustache.php

我们希望(重新)构建一个网络应用程序。我们想使它同构,因此服务器可以呈现相同的模板,但是存在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

中处理选择的更好方法,那似乎很奇怪

(注意:这是我所拥有的简化版本:我们对数据进行了分类,因此我有一个双索引(类别,然后是名称)和更多字段。由于这个原因,可能会出现一些小错误。以上)

1 个答案:

答案 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}}

有很多方法可以做到,但这应该让你开始。