Как сохранить исходное значение выбранным при переходе в режим редактирования? - PullRequest
0 голосов
/ 23 февраля 2012

Выбранные списки не отображаются с выбранной верной опцией.Я пробовал это различными способами, включая вычисляемую выбранную наблюдаемую (this.selected = ko.computed (возвращаемое parseInt (selected (), 10) == this.id;)) и поиск в функциях массива.

В производстве элементы dataArea будут заполняться данными на стороне сервера.Использование элементов div с атрибутами «data-» позволяет разделять сценарии на стороне сервера и на стороне клиента (я считаю, что это помогает дизайнерам).

Запись будет отображаться в режиме без редактирования, и сначала можно будет изменить ее, нажав кнопкукнопка редактирования.В режиме редактирования начальные значения записи отображаются в элементах управления вводом.У вас будет возможность сказать, выбрать другого клиента и при наличии формы загрузить новые связанные проекты.Загрузка нового клиента приведет к сбросу списка проектов, как и ожидалось.

Таким образом, при загрузке нового клиента будет работать хорошо, его переход к редактированию текущих значений вызывает проблему.Выбранный проект должен появиться в раскрывающемся списке.Если выбран новый клиент, список заполняется новыми параметрами, и значения по умолчанию не требуются.

http://jsfiddle.net/mathewvance/ZQLRx/

* исходный образец (игнорируйте) http://jsfiddle.net/mathewvance/wAGzh/*

Спасибо.

<p>
    issue: When the select options are read, the inital value gets reset to the first object in the options. How do I keep the original value selected when transitioning to edit mode?
</p>

<div>
    <h2>Edit Quote '1001'</h2>

    <div class="editor-row" data-bind="with: selectedCustomer">
        <label>Customer</label>
        <div data-bind="visible: !$root.isEditMode()">
            <span data-bind="text: CompanyName"></span>
        </div>
        <div data-bind="visible: $root.isEditMode()">
            <input type="radio" name="customerGroup" value="1" data-bind="value: id"> Company Name 1
            <input type="radio" name="customerGroup" value="2" data-bind="value: id"> Company Name 2
        </div>
    </div>

    <div class="editor-row">
        <label>Project</label>
        <div data-bind="visible: !isEditMode()">
            <span data-bind="text: selectedProject.Name"></span>
        </div>
        <div data-bind="visible: isEditMode()">
            <select data-bind="options: selectedCustomer().projects, optionsText: 'Name', value: selectedProject"></select>
        </div>
    </div>

    <div>
        <button data-bind="click: function() { turnOnEditMode() }">Edit</button>
        <button data-bind="click: function() { turnOffEditMode() }">Cancel</button>
    </div>
</div>

<hr/>

<div data-bind="text: ko.toJSON($root)"></div>

function ajaxCallGetProjectsByCustomer(customerId) {
    var database = '[{"CustomerId": 1, "Name":"Company Name 1", "Projects": [ { "ProjectId": "11", "Name": "project 11" }, { "ProjectId": "12", "Name": "project 12" }, { "ProjectId": "13", "Name": "project 13" }] }, {"CustomerId": 2, "Name": "Company Name 2", "Projects": [ { "ProjectId": "21", "Name": "project 21" }, { "ProjectId": "22", "Name": "project 22" }, { "ProjectId": "23", "Name": "project 23" }] }]';

    var json = ko.utils.parseJson(database);
    //console.log('parseJson(database) - ' + json);

    //ko.utils.arrayForEach(json, function(item) {
    //    console.log('CustomerId: ' + item.CustomerId);
    //});

    return ko.utils.arrayFirst(json, function(item){
        return item.CustomerId == customerId;
    });
}

var Customer = function(id, name, projects) {
    var self = this;

    this.id = ko.observable(id);
    this.CompanyName = ko.observable(name);

    this.projects = ko.observableArray(ko.utils.arrayMap(projects, function(item) {
        return new Project(item.ProjectId, item.Name);
    }));
};

Customer.load = function(id) {
    var data =  ajaxCallGetProjectsByCustomer(id);

    var customer = new Customer(
        data.CustomerId,
        data.Name,
        data.Projects);
 };

var Project= function(id, name) {
    this.id = id;
    this.Name = ko.observable(name);
 };

var QuoteViewModel = function () {
    var self = this;

    $customerData = $('#customerData'); // data from html elements
    $projectData = $('#projectData');

    // intial values to display from html data
    var customer = new Customer (
        $customerData .attr('data-id'),
        $customerData .attr('data-companyName'),
        [{"ProjectId": $projectData .attr('data-id'), "Name": $projectData .attr('data-name')}]
    )

    this.selectedCustomer = ko.observable(customer);
    this.selectedProject = ko.observable($projectData.attr('data-id'));

    this.isEditMode = ko.observable(false);

    this.selectedCustomer.subscribe(function(){
        // todo: load customer projects from database api when editing
    });

    this.turnOnEditMode = function() {
        var customerId = self.selectedCustomer().id();
        console.log('customerId: ' + customerId);
        Customer.load(customerId);
        self.isEditMode(true);
    };

    this.turnOffEditMode = function() {
        self.isEditMode(false);
    };
};

var viewModel = new QuoteViewModel();
ko.applyBindings(viewModel);

1 Ответ

0 голосов
/ 23 февраля 2012

Одно начальное значение, которое вы загружаете

this.dongle = ko.observable($dongleData.attr('data-id'));

Это будет строковое значение "3". Где в качестве ключа выбора HTML-элемент фактически сохраняет / ожидает получить объект { "Id": "3", "Name": "dongle 3" }.

Вот рабочая версия, которая получает правильные начальные значения и позволяет редактировать.

http://jsfiddle.net/madcapnmckay/28FVr/5/

Если вам нужно сохранить определенное значение, а не весь объект ключа / виджета, вы можете использовать атрибут optionsValue для хранения только идентификатора. Вот так работает.

http://jsfiddle.net/madcapnmckay/VnjyT/4/

EDIT

Хорошо, у меня есть рабочая версия для вас. Я постараюсь обобщить все, что я изменил и почему.

http://jsfiddle.net/madcapnmckay/jXr8W/

Чтобы получить информацию о клиенте для работы

Имя клиента не было сохранено в ajaxCallGetProjectsByCustomer json, поэтому при загрузке клиента не было возможности определить новое имя по полученным данным. Я добавил свойство Name каждому клиенту в json с именем «Название компании 1» и т. Д.

Чтобы заставить работать коллекцию проектов

Проблема здесь была, как было заявлено изначально с ключами. Вы инициализируете наблюдаемую selectedProject с помощью $projectData.attr('data-id'), что соответствует строковому значению 13. Это неверно, поскольку список выбора настроен таким образом, что он фактически сохраняет / ожидает получения самого объекта проекта. Изменение этого присвоения идентификатора на присвоение объекта сделало правильное начальное значение работы проекта.

var project = ko.utils.arrayFirst(customer.projects(), function(project){
    return project.id == Number($projectData.attr('data-id'));
});

this.selectedProject = ko.observable(project);

К вашему сведению, в html произошла небольшая ошибка, для selectedProject.Name нужно было выбрать selectedProject (). Name. Ничего страшного.

Уверен, вы могли бы довольно легко это выяснить. Следующий бит - вот где настоящая проблема. Вы перезагружаете Клиента каждый раз, когда нажимаете кнопку редактирования. Это кажется странным, и вы можете пересмотреть этот подход.

Однако, что происходит, вы загружаете объект клиента с сервера по идентификатору. Присвойте его выбранному клиенту, это реально работает нормально. Но тогда, поскольку раскрывающийся список привязан к selectedCustomer().projects и viewModel.selectedProject, он ожидает, что selectedProject является членом selectedCustomer (). Projects. В случае объектов оператор равенства оценивает, совпадают ли ссылки, а в вашем случае - нет, потому что исходный selectedProject был уничтожен вместе с ассоциированным клиентом, когда вы перезаписали значение selectedCustomer. Тот факт, что идентификаторы одинаковы, не имеет значения.

Я решил взломать эту проблему.

var oldProjectId = viewModel.selectedProject().id;
viewModel.selectedCustomer(customer);

var sameProjectDifferentInstance = ko.utils.arrayFirst(customer.projects(), function(project){
    return project.id == oldProjectId;
});

viewModel.selectedProject(sameProjectDifferentInstance || customer.projects()[0]);

Это сохраняет старый идентификатор проекта перед назначением нового клиента, ищет объект проекта в новом объекте клиента и присваивает его или по умолчанию первый, если не найден.

Я бы порекомендовал переосмыслить, когда вы загружаете объекты и как вы справляетесь с их жизненным циклом. Если вы храните текущие объекты в памяти с полным списком включенных проектов, вам не нужно загружать их для редактирования, просто отредактируйте и затем отправьте обновление обратно на сервер.

Возможно, вам будет проще хранить json с сервера в переменных js вместо элементов html dom. например,

<script>var projectInitialData = '@Model.ProjectInitialData.toJSON()';</script>

Надеюсь, это поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...