Knockout.js добавляет элемент в foreach из вызова ajax

У меня есть такая модель просмотра

function AppViewModel() {
    var self = this;

    self.blogUpdate = ko.observableArray();
}

var vm = new AppViewModel();

$(document).ready(function () {
    $.getJSON('/Blog/GetUpdates?id=89', function (response) {
        vm.blogUpdate = ko.observableArray(response);
        ko.applyBindings(vm);
    });
});

<table>
    <thead>
        <tr><th>First name</th><th>Last name</th></tr>
    </thead>
    <tbody data-bind = "foreach: blogUpdate">
        <tr>
            <td data-bind = "text: title"></td>
            <td data-bind = "text: body"></td>
        </tr>
    </tbody>
</table>

У меня есть кнопка, которая открывает динамически созданный модальный / диалог с вводом формы. При отправке он отправляет обратно через ajax, а в функции успеха я пытаюсь отправить только что созданный JSON.

        $.ajax({
            type: 'POST',
            global: false,
            url: '/Blog/NewUpdate',
            data: $form.serialize(),
            success: function (response) {
                vm.blogUpdate.push(response)
            }
        });

Если я обращаюсь к массиву, я вижу его там, но интерфейс не обновляется. В примерах, которые я вижу, на кнопке используется data-bind = "click: updateFunc". Но моя кнопка просто открывает модальное окно, которое позволяет вам вводить текст и сообщения ajax обратно.

Как я могу заставить это работать?

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
0
126
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

https://jsfiddle.net/wvwh2x3n/1/

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

success: function (response) {
    var parsed = JSON.parse(response);
    vm.blogUpdate.push(new BlogPost{ parsed.prop1, parsed.prop2 })
}

var BlogPost = function(prop1, prop2) {
    var self = this;
    self.prop1 = ko.observable(ko.utils.unwrapObservable(prop1));
    self.prop2 = ko.observable(ko.utils.unwrapObservable(prop2));
}

Вы должны использовать data-bind = "modal: xyz", как показано на скрипке. Только не забывайте о работе по настройке привязок и т. д.

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

я люблю нокаут: D

HTML

<div class = "row">
  <div class = "col-sm-6 col-sm-offset-3">
    <ul data-bind = "foreach: Users" class = "list-group hover">
      <li class = "list-group-item">
        <div class = "row">
          <div class = "col-xs-6">
          </div>
          <div class = "col-xs-2">
          </div>
          <div class = "col-xs-4 text-right">
            <a href = "#" data-bind = "click: $parent.EditUser">Show modal</a> |
          </div>
        </div>
      </li>
    </ul>
  </div>
</div>

<div data-bind = "modal: UserBeingEdited" class = "fade" role = "dialog" tabindex = "-1">
  <form>
    <div class = "modal-header">
      <a class = "close" data-dismiss = "modal">×</a>
      <h3>User Details</h3>
    </div>
    <div class = "modal-body">
      <div class = "form-group">
        <label for = "NameInput">Name</label>
        <input type = "text" class = "form-control" id = "NameInput" placeholder = "User's name" data-bind = "value: UserBeingEdited() && UserBeingEdited().Name, valueUpdate: 'afterkeydown'">
      </div>
      <div class = "form-group">
        <label for = "AgeInput">Age</label>
        <input type = "text" class = "form-control" id = "AgeInput" placeholder = "User's age" data-bind = "value: UserBeingEdited() && UserBeingEdited().Age, valueUpdate: 'afterkeydown'">
      </div>
      <!-- /ko -->
    </div>
    <div class = "modal-footer">
      <button type = "button" data-dismiss = "modal" class = "btn btn-default">Cancel</button>
      <button type = "submit" class = "btn btn-primary">Save Changes</button>
    </div>
  </form>
</div>

CSS

/**** These styles are here to override the styles in 'bootstrap-modal-bs3patch.css' ****/

$screen-sm-min = 768px; //<== Standard Bootstrap width

.modal {
  left: 25%;
  width: 50% !important;

  @media screen and (-webkit-min-device-pixel-ratio:0) { 
    /* Safari and Chrome */
    left: 50%;
    width: 500px;
  }

  @media (max-width: $screen-sm-min) {
    left: 0;
    width: 100% !important;
  }
}

JS

ko.bindingHandlers['modal'] = {
  init: function(element, valueAccessor, allBindingsAccessor) {
    var allBindings = allBindingsAccessor();
    var $element = $(element);
    $element.addClass('hide modal');

    if (allBindings.modalOptions && allBindings.modalOptions.beforeClose) {
      $element.on('hide', function() {
        var value = ko.utils.unwrapObservable(valueAccessor());
        return allBindings.modalOptions.beforeClose(value);
      });
    }
  },
  update: function(element, valueAccessor) {
    var value = ko.utils.unwrapObservable(valueAccessor());
    if (value) {
      $(element).removeClass('hide').modal('show');
    } else {
      $(element).modal('hide');
    }
  }
};

/* ViewModel for the individual records in our collection. */
var User = function(name, age) {
  var self = this;
  self.Name = ko.observable(ko.utils.unwrapObservable(name));
  self.Age = ko.observable(ko.utils.unwrapObservable(age));
}

/* The page's main ViewModel. */
var ViewModel = function() {
  var self = this;
  self.Users = ko.observableArray();

  // The instance of the user currently being edited.
  self.UserBeingEdited = ko.observable();

  // Used to keep a reference back to the original user record being edited
  self.OriginalUserInstance = ko.observable();


  self.EditUser = function(user) {
    // Keep a copy of the original instance so we don't modify it's values in the editor
    self.OriginalUserInstance(user);

    // Copy the user data into a new instance for editing
    self.UserBeingEdited(new User(user.Name, user.Age));

  }
}

var viewModel = new ViewModel();

// Populate the ViewModel with some dummy data
for (var i = 1; i <= 10; i++) {
  var letter = String.fromCharCode(i + 64);
  var userName = 'User ' + letter;
  var userAge = i * 2;
  viewModel.Users.push(new User(userName, userAge));
}

// Let Knockout do its magic!
ko.applyBindings(viewModel);

На самом деле это сработало. По какой-то причине я ожидал, что он появится вверху, но вместо этого он появился внизу. Необходимо использовать unshift вместо push.

Jack 17.03.2018 11:45

Другие вопросы по теме