设置模板中下拉列表的 selectedValue (加载时)

发布于 2024-12-01 13:16:37 字数 3236 浏览 0 评论 0原文

我在下拉列表中遇到一些问题,我需要将初始值传递给视图模型,因此下拉列表将填充已选择的值。

据我所知(参见这个小提琴):

var additionalTravellersDetails = [
    { id: 1, firstName: "George", middleName: "", lastName: "Washington ", AcNum: "12345678" }, 
    { id: 2, firstName: "Abraham ", middleName: "", lastName: "Lincoln", AcNum: "23758383" },
    // etc
];

function Traveller(id, AcNum) {
    this.id = ko.observable(id);
    this.categoryId = ko.observable();
}

Traveller.prototype.getUniqueCategories = function () {
    var thisCategoryId = parseInt(this.categoryId(), 10);
    return ko.utils.arrayFilter(additionalTravellersDetails, function (additionalTravellersDetails) {
        return (additionalTravellersDetails.id === thisCategoryId) || !viewModel.usedCategoryIndex()[additionalTravellersDetails.id];
    });
}

var viewModel = {
    TravRows: ko.observableArray([]),
    addTravRow: function () {
        this.TravRows.push(new Traveller());
    },
    removeTravRow: function (Traveller) {
        this.TravRows.remove(Traveller);
    },

    noOfTrav: ko.observableArray(['1', '2', '3', '4', '5', '6', '7', '8', '9']),
    SelectedNo: ko.observable('1')
};

viewModel.usedCategoryIndex = ko.dependentObservable(function () {
    var result = {};
    ko.utils.arrayForEach(this.TravRows(), function (Traveller) {
        var cat = Traveller.categoryId();
        if (cat) {
            result[cat] = 1;
        }
    });
    return result;
}, viewModel);

viewModel.TravRows.push(new Traveller());

ko.applyBindings(viewModel);

// On Num of Trav Select index change
$("#nrTravelers").change(function () {
    var len = viewModel.noOfTrav().length;
    for (var i = 0; i < len; i++) {
        viewModel.removeTravRow(viewModel.TravRows()[0]);
    }
    for (var i = 0; i < $(this).val(); i++) {
        viewModel.addTravRow();
    }
});

这是相应的视图:

<p>Number of travellers:
    <select id="nrTravelers" data-bind="options: noOfTrav,  selectedOptions: SelectedNo"></select>
</p>
<table data-bind="template: {name:'AdditionalTravelersTemplate', foreach: TravRows}"></table>
<script id="AdditionalTravelersTemplate" type="text/html">
    <tr>
        <th>Traveler<span>1</span></th> //TODO: replace 1 with the auto num
    </tr>
    <tr>
        <td>
            <select data-bind="options: getUniqueCategories(), 
                               optionsText: function(item) {
                                   return item.lastName+ ' , ' + item.firstName+ ' - '+ item.AcNum }, 
                               optionsValue: 'id', 
                               optionsCaption: 'choose one...', 
                               value: categoryId"></select > 
        </td>
    </tr >
</script>

以下是上面代码中我需要的内容:

  1. 我想用已选择的值预先填充所有下拉列表
  2. 当列表不再包含任何旅行者时,我想在下拉列表中显示一些
  3. 我想添加的 文本每个“旅行者”文本后面都有一个数字下拉列表

我已经解决了的第二个要求,还有两个要求。

附言。我已经对第一个要求的某些部分进行了硬编码,请告诉我该方法是否可以?

有什么建议/想法吗?

I'm having some issues with a drop-down list where I need to pass the initial value to the view model so, the drop-down list will be populated with an already-selected value.

This is as far as I got (see this fiddle):

var additionalTravellersDetails = [
    { id: 1, firstName: "George", middleName: "", lastName: "Washington ", AcNum: "12345678" }, 
    { id: 2, firstName: "Abraham ", middleName: "", lastName: "Lincoln", AcNum: "23758383" },
    // etc
];

function Traveller(id, AcNum) {
    this.id = ko.observable(id);
    this.categoryId = ko.observable();
}

Traveller.prototype.getUniqueCategories = function () {
    var thisCategoryId = parseInt(this.categoryId(), 10);
    return ko.utils.arrayFilter(additionalTravellersDetails, function (additionalTravellersDetails) {
        return (additionalTravellersDetails.id === thisCategoryId) || !viewModel.usedCategoryIndex()[additionalTravellersDetails.id];
    });
}

var viewModel = {
    TravRows: ko.observableArray([]),
    addTravRow: function () {
        this.TravRows.push(new Traveller());
    },
    removeTravRow: function (Traveller) {
        this.TravRows.remove(Traveller);
    },

    noOfTrav: ko.observableArray(['1', '2', '3', '4', '5', '6', '7', '8', '9']),
    SelectedNo: ko.observable('1')
};

viewModel.usedCategoryIndex = ko.dependentObservable(function () {
    var result = {};
    ko.utils.arrayForEach(this.TravRows(), function (Traveller) {
        var cat = Traveller.categoryId();
        if (cat) {
            result[cat] = 1;
        }
    });
    return result;
}, viewModel);

viewModel.TravRows.push(new Traveller());

ko.applyBindings(viewModel);

// On Num of Trav Select index change
$("#nrTravelers").change(function () {
    var len = viewModel.noOfTrav().length;
    for (var i = 0; i < len; i++) {
        viewModel.removeTravRow(viewModel.TravRows()[0]);
    }
    for (var i = 0; i < $(this).val(); i++) {
        viewModel.addTravRow();
    }
});

And this is the corresponding view:

<p>Number of travellers:
    <select id="nrTravelers" data-bind="options: noOfTrav,  selectedOptions: SelectedNo"></select>
</p>
<table data-bind="template: {name:'AdditionalTravelersTemplate', foreach: TravRows}"></table>
<script id="AdditionalTravelersTemplate" type="text/html">
    <tr>
        <th>Traveler<span>1</span></th> //TODO: replace 1 with the auto num
    </tr>
    <tr>
        <td>
            <select data-bind="options: getUniqueCategories(), 
                               optionsText: function(item) {
                                   return item.lastName+ ' , ' + item.firstName+ ' - '+ item.AcNum }, 
                               optionsValue: 'id', 
                               optionsCaption: 'choose one...', 
                               value: categoryId"></select > 
        </td>
    </tr >
</script>

The following are the things I need in the above code:

  1. I want to pre populate all the drop-down lists with already selected values
  2. When the list does not contain any more travelers, I want to display some text in the drop down list
  3. I want to add a number after "Traveler" text for each drop-down list

The 2nd requirement I have solved, two more to go.

PS. I have hard coded some part for the first requirement, please tell me if the approach is OK?

Any suggestions/ideas please?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

汹涌人海 2024-12-08 13:16:37

这里有一些想法: http://jsfiddle.net/rniemeyer/P6aDk/

索引,您可以使用 jQuery 模板中的 {{each}} ,或者仍然获得 KO 的 foreach 好处的简单方法是创建手动订阅到您的 observableArray 并更新/创建一个属性来保存该位置。这就像:

viewModel.TravRows.subscribe(function(currentValue) {
    for (var i = 0, j = currentValue.length; i < j; i++) {
       var row = currentValue[i];
        if (!row.position) {
           row.position = ko.observable(i+1);  
        } else {
           row.position(i+1);   
        }  
    }
});

现在,每一行都有一个可以绑定的“位置”可观察对象,并且它们将随着数组的变化而保持更新。

对于添加/删除行,您可以添加针对 SelectedNo observable 的订阅,当它发生更改时,您可以协调实际行数。例如:

viewModel.SelectedNo.subscribe(function(newValue) {
    var actualLen = viewModel.TravRows().length,
        expectedLen = parseInt(newValue, 10);

    if (actualLen < expectedLen) {
        for (var i = actualLen; i < expectedLen; i++) {
           viewModel.addTravRow();  
        }
    } else {
        for (var i = actualLen; i > expectedLen; i--) {
            viewModel.removeTravRow(viewModel.TravRows()[i]);
        }
    }
});  

为了设置现有数据,我更改了每行下拉列表上的 value 绑定,以绑定 id。然后,我将初始数据设置为包含两个旅行者及其 ID。您可以将其切换为帐号或任何合适的名称。

Here are a couple of ideas here: http://jsfiddle.net/rniemeyer/P6aDk/

For the index, you could either use {{each}} from jQuery template's or an easy way to still get the benefits of KO's foreach is to create a manual subscription to your observableArray and update/create a property to hold the position. This would be like:

viewModel.TravRows.subscribe(function(currentValue) {
    for (var i = 0, j = currentValue.length; i < j; i++) {
       var row = currentValue[i];
        if (!row.position) {
           row.position = ko.observable(i+1);  
        } else {
           row.position(i+1);   
        }  
    }
});

Now, each row will have a "position" observable that you can bind against and they will stay updated as the array changes.

For, adding/removing rows, you could add a subscription against the SelectedNo observable and when it changes you can reconcile the actual number of rows. Like:

viewModel.SelectedNo.subscribe(function(newValue) {
    var actualLen = viewModel.TravRows().length,
        expectedLen = parseInt(newValue, 10);

    if (actualLen < expectedLen) {
        for (var i = actualLen; i < expectedLen; i++) {
           viewModel.addTravRow();  
        }
    } else {
        for (var i = actualLen; i > expectedLen; i--) {
            viewModel.removeTravRow(viewModel.TravRows()[i]);
        }
    }
});  

For setting existing data, I changed the value binding on the dropdown for each row to bind against the id. Then, I set the initial data to include two Travellers with their ids. You could switch this to account number or whatever is appropriate.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文