Динамическое отображение контента на основе пользовательского ввода

Это мое первое приложение Knockout.js, поэтому я собираюсь немного упростить свой код, чтобы проиллюстрировать, чего я пытаюсь достичь.

У меня есть настройка модели представления следующим образом:

function Product(data) {
    this.productName = data.productName;
    this.serialNumber = data.serialNumber;
    this.version = ko.observable(data.version);
    this.isSelected = ko.observable(data.IsSelected);
}

function RestoreViewModel() {
    var self = this;

    //Properties
    self.allCustomerProducts = ko.observableArray([]);

    //Computations
    self.selectedProducts = ko.computed(function() {
        return ko.utils.arrayFilter(self.allCustomerProducts(), function(product) { return product.isSelected() });
    });
}

и некоторые настройки разметки следующим образом:

<div id="Version1">
   <div class="product1"><a href="">download link goes here.</a></div>
   <div class="product2"><a href="">download link goes here.</a></div>
   <div class="product3"><a href="">download link goes here.</a></div>
</div>

<div id="Version2">
   <div class="product1"><a href="">download link goes here.</a></div>
   <div class="product2"><a href="">download link goes here.</a></div>
   <div class="product3"><a href="">download link goes here.</a></div>
</div>

Это делается так: у пользователя есть список продуктов, которые он выбирает, а затем для каждого продукта он выбирает версию. Это работает как надо, поэтому можно предположить, что вычисляемый метод selectedProducts возвращает правильный массив с правильными данными.

Что я не смог понять после многих попыток, так это то, как я могу отображать загрузки на основе выбора продукта и версии?

Если пользователь выбирает продукт1 и версию 1, а затем также выбирает продукт1 и версию 2, мне нужно, чтобы эти соответствующие элементы отображались.

Если что-то в моей модели представления или моя разметка HTML должна отличаться, я готов переработать это, чтобы сделать его правильным.

Изменить. Вот иллюстрация, показывающая настройки и желаемый результат:

Пример


person Justin Helgerson    schedule 20.09.2012    source источник
comment
Посмотрите мой ответ на этот вопрос: stackoverflow.com/a/12516575/390278. Вы можете применить те же концепции к этому вопросу.   -  person Jeff Mercado    schedule 20.09.2012
comment
@JeffMercado - я мог бы использовать этот подход, но если вы посмотрите на мою иллюстрацию, вы увидите, что пользователь фактически может выбрать версию (среду в примере, на который вы ссылаетесь) для каждого продукта. Это привело бы к тому, что мне пришлось бы создавать вычисляемый метод для каждого раздела загрузки. Есть ли у вас какие-либо идеи о том, как я могу сделать его динамичным? В качестве альтернативы, чтобы я мог создать один метод и использовать параметры, чтобы мне не приходилось создавать несколько методов?   -  person Justin Helgerson    schedule 20.09.2012
comment
Конечно, то, что вы пытаетесь сделать, кажется достаточно простым. Не могли бы вы настроить скрипку для начала? Я бы сделал это сам, но я немного занят.   -  person Jeff Mercado    schedule 20.09.2012
comment
@JeffMercado - я ценю ваш ответ и время. Вот скрипка, которая, как мне кажется, отображает то, что я пытаюсь сделать: jsfiddle.net/Ek0nomik/Sk6Lm /1   -  person Justin Helgerson    schedule 21.09.2012


Ответы (1)


Вот: Обновленная скрипта

Таким образом, весь план состоял в том, чтобы взять этот массив выбранных продуктов и создать массив объектов, представляющий набор загрузок для этого массива. Чтобы получить этот массив, логика находится в функции getSelectedDownloads. Просто прямая группировка по версии и отображению.

var getSelectedDownloads = function() {
    var selectedProducts = self.selectedProducts();
    var versions = ko.utils.arrayGetDistinctValues(
        ko.utils.arrayMap(selectedProducts, function (item) { return item.version(); })
    ).sort().reverse();

    return ko.utils.arrayMap(versions, function (version) {
        var items = ko.utils.arrayFilter(selectedProducts, function (item) {
            return item.version() == version;
        }).sort(function (a, b) {
            var x = a.displayName, y = b.displayName;
            return x < y ? -1 : (x > y ? 1 : 0);
        });
        return {
            verid: version.replace(/\./g, ''),
            header: version.replace(/(\d).*/, 'Version $1 Downloads'),
            items: ko.utils.arrayMap(items, function (item) {
                return {
                    label: item.displayName + ' Software',
                    url: '#' //set your urls here
                };
            })
        };
    });
};

Таким образом, каждый объект будет содержать свойства verid, header и items (где элементы представляют собой ссылки), к которым вы затем можете привязаться.

<div id="downloads" data-bind="foreach: selectedDownloads">
    <div data-bind="attr: { id: verid }">
        <h5 data-bind="text: header"></h5>
        <ul data-bind="foreach: items">
            <li>
                <a data-bind="text: label, attr: { href: url }"></a>
            </li>
        </ul>
    </div>
</div>
person Jeff Mercado    schedule 20.09.2012