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

Я использую mvc4 и entityframework в сочетании с нокаутом. Я также использую нокаут-мэппинг. Но столкнулся с проблемой, которую не могу решить.

Чего я хочу достичь:

  • Пользователь нажимает кнопку «Удалить», чтобы удалить строку из таблицы. [Работает]
  • Вызовите метод действия удаления на контроллере mvc, чтобы фактически удалить данные из базы данных. [Работает]
  • Отправьте обратно новый объект Json, содержащий данные новой измененной таблицы. [Работает]
  • Загрузите новые данные в мою нокаутирующую модель просмотра и обновите пользовательский интерфейс, используя ko.mapping.fromJS() and ko.applyBindings() [Не работает, и я действительно потерялся здесь]

Похоже, я полностью потерял ссылку на свой список опыта, который я использую для привязки данных и для каждой таблицы. И я думаю, что это связано с тем, как я вызываю свой метод удаления из цикла foreach.

Также похоже, что «уловка» javascript с var self = this; не работает, чтобы получить мою ссылку на правильные данные.

Ниже следует мой код, который я сейчас использую, чтобы дать вам лучшее представление о ситуации. Если требуется дополнительная информация, пожалуйста, дайте мне знать.

Это мои модели просмотра mvc:

public class ExperienceOverviewModel
{
        public ExperienceModel selectedExperience { get; set; }
        public List<ExperienceModel> Experiences { get; set; }
}

public class ExperienceModel
{
        public int ExperienceId { get; set; }
        public DateTime DateFrom { get; set; }
        public DateTime DateUntil { get; set; }
        public string Description { get; set; }
        public string Employer { get; set; }
        public decimal Hours { get; set; }
        public int PersonId { get; set; }
        public bool? Secondment { get; set; }
        public string Title { get; set; }
}

Это моя таблица, в которой я foreach связываю данные с опытом, используя нокаут:

</table>
    <thead>
        </thead> 
    <tbody data-bind="foreach: Experiences()">
            <tr>
                <td data-bind="text: Employer"></td>
                <td data-bind="text: Description"></td>
                <td data-bind="text: DateFrom"></td>
                <td data-bind="text: DateUntil"></td>
                <td data-bind="text: Secondment"></td>
                <td>
                    <a href="#" data-bind="click: function(data, event){ $root.EditExperienceModal(data); }"><i class="icon-edit"></i></a>
                </td>
                <td>
                    <a href="#" data-bind="click: function(data, event){ $root.ConfirmDeleteExperienceModal(data);}"><i class="icon-remove"></i></a>
                </td>
            </tr>
        </tbody>
    </table>

Моя нокаутирующая модель просмотра, в которой я хочу вызвать ko.mapping.fromJS() и ko.applyBindings()... Вот это фубар....

    function ViewModel() {
            this.DeleteExperience = function (experience) {

                $.ajax({
                    type: "post",
                    contentType: "application/json",
                    url: "/Experienced/Delete/" + this.selectedExperience.ExperienceId(),
                    data: ko.toJSON(self.selectedExperience),
                    error: function (xhr, status, error) {
                    },
                    success: function (response) {

                        ko.mapping.fromJS(response, ?? this.Experiences ??);  <---- ???
                        ko.applyBindings(?????);                              <---- ???

                    }
                });
            }
        }

        $(function () {
            var jsonModel = '@Html.Raw(Newtonsoft.Json.JsonConvert.SerializeObject(this.Model, new Newtonsoft.Json.Converters.IsoDateTimeConverter()))';
            var mvcModel = ko.mapping.fromJSON(jsonModel);

            var myViewModel = new ViewModel();
            g = ko.mapping.fromJS(myViewModel, mvcModel);
            ko.applyBindings(g);
        });

* -- ОБНОВЛЕНО -- *

Чтобы уточнить, вот что я упростил: когда я получаю результаты от вызова AJAX, я получаю следующую ошибку:

Объект # не имеет метода «Впечатления»

<table class="table table-striped">
    <tbody data-bind="foreach: Experiences()">
        <tr>
            <td data-bind="text: Employer"></td>
            <td data-bind="text: Description"></td>
            <td data-bind="text: DateFrom"></td>
            <td data-bind="text: DateUntill"></td>
            <td data-bind="text: Secondment"></td>
            <td>
               <a href="#" data-bind="click: $root.DeleteExperience"><i class="icon-remove"></i></a>

            </td>
        </tr>
    </tbody>
</table>
<script type="text/javascript">

    function ViewModel() {
        var self = this;

        self.DeleteExperience = function (experience) {
            $.ajax({
                type: "post",
                contentType: "application/json",
                url: "/Experienced/Delete/" + experience.ExperienceId(),
                data: ko.toJSON(experience),
                error: function (xhr, status, error) {
                    console.log(error);
                },
                success: function (response) {
                    $('#confirmDeleteModal').modal('hide');
                    self.UpdateExperienceList(response);
                }
            });
        }

        self.UpdateExperienceList = function (data) {
            self.Experiences(data);       <---- ?????
        }
    }

    $(function () {
        var jsonModel = '@Html.Raw(Newtonsoft.Json.JsonConvert.SerializeObject(this.Model, new Newtonsoft.Json.Converters.IsoDateTimeConverter()))';
        var mvcModel = ko.mapping.fromJSON(jsonModel);
        var myViewModel = new ViewModel();
        g = ko.mapping.fromJS(myViewModel, mvcModel);
        ko.applyBindings(g);
    });
</script>

person user1853542    schedule 09.04.2013    source источник
comment
Можете ли вы опубликовать код, определяющий this.Experiences? Вы почти наверняка не сможете использовать здесь this. - объект this внутри вашего обратного вызова success не такой, как в вашей функции ViewModel...   -  person Steve Greatrex    schedule 09.04.2013
comment
Спасибо, но у меня все та же проблема, я обновил свой вопрос, чтобы прояснить проблему.   -  person user1853542    schedule 09.04.2013
comment
Где вы создаете экземпляр self.Experiences?   -  person Steve Greatrex    schedule 09.04.2013
comment
self.Experiences исходит из моей модели просмотра mvc4. он сопоставляется с нокаутом. в этой строке var jsonModel = '@Html.Raw(Newtonsoft.Json.JsonConvert.SerializeObject(this.Model, new Newtonsoft.Json.Converters.IsoDateTimeConverter()))';   -  person user1853542    schedule 09.04.2013


Ответы (2)


В вашей функции self.UpdateExperienceList попробуйте следующее:

self.UpdateExperienceList = function(data) {
    ko.mapping.fromJSON(data, {}, self);
};

Это обновит свойства объекта self на основе данных с сервера.

Ваше первоначальное создание модели представления также кажется мне неправильным. Я бы хотел, чтобы вы хотели что-то большее, как показано ниже:

var myViewModel = ko.mapping.fromJSON(jsonModel, {}, new ViewModel());
person Steve Greatrex    schedule 09.04.2013
comment
Спасибо! Я знаю, что нужно инициализировать все с помощью: var myViewModel = ko.mapping.fromJSON(jsonModel, {}, new ViewModel()); и self.UpdateExperienceList = функция (данные) { ko.mapping.fromJSON (данные, {}, self.Experiences); } Наконец-то работает! Спасибо! - person user1853542; 09.04.2013

Я не думаю, что вам нужно снова звонить ko.applyBindings(?????);. Вы должны явно определить свою модель представления:

function MyModel() {
    var self = this;

    self.Data = ko.observableArray([{"Name": "Lionel Messi", "Occupation": "Football player"}, {"Name": "Jason Mraz", "Occupation": "Singer"}, {"Name": "Nicolas Cage", "Occupation": "Film Actor"}]);

    self.update = function(data) {
        self.Data(data);
    }
}

$(function(){
    var model = new MyModel();
    ko.applyBindings(model);
});

Как вы видите, я определяю self.update, вы просто вызываете эту функцию и обновляете свои данные, и в случае, если вы хотите удалить строку из таблицы, вы просто splice эту строку из self.Data()

person Phong Vo    schedule 09.04.2013
comment
Спасибо за ваш вклад, но это не решение, я обновил свой исходный вопрос, чтобы упростить мою проблему. - person user1853542; 09.04.2013