У меня есть модель с несколькими вложенными наблюдаемыми массивами, и мне нужно вызвать функцию для удаления элементов из одного из массивов. Вместо диаграммы я попытаюсь описать модель на английском языке (она также включена ниже в код). Модель представления - это план обучения, который имеет наблюдаемый массив недельных объектов. Каждый объект недели, среди других свойств, имеет объект observableArray of Days. Каждый день объект, среди других свойств, имеет наблюдаемый массив объектов тренировки. Каждый объект тренировки, среди других свойств, имеет наблюдаемый массив объектов Interval. Я новичок в нокауте и не все, что у меня на ногах с javascript (и, возможно, некоторые вещи здесь не так, пожалуйста, не стесняйтесь критиковать). Проблема заключается в функции removeWorkout на объекте Day. Я следую примеру 2 на сайте нокаута здесь: example. Я думаю, что я делаю то, что говорит страница, но когда я проверяю «это» в функции, это объект «День», а не «объект тренировки», который вызывает эту функцию. Где я иду не так?Вызывающие функции в вложенных наблюдаемых массивах (knockout.js)
Мой Javascript Файл:
$(document).ready(function() {
var trainingPlan;
var weekNumber = 0;
var workoutNumber = 0;
var planID = { id: $('#ID').val() };
$.getJSON('/PlanBuilder/GetPlanJson', planID, function (model) {
trainingPlan = ko.mapping.fromJSON(model.Message);
trainingPlan.addWeek = function() {
var wk = new week();
weekNumber++;
wk.Name = 'Week ' + weekNumber;
for (var i = 1; i < 8; i++) {
var dy = new day();
dy.DayNumber = i;
wk.Days.push(dy);
}
var summ = new day();
summ.DayNumber = "Summary";
wk.Days.push(summ);
this.Schedule.push(wk);
};
ko.applyBindings(trainingPlan);
});
function week() {
this.PlanID = ko.observable();
this.StartDate = ko.observable();
this.EndDate = ko.observable();
this.Name = ko.observable();
this.Days = ko.observableArray(); // a list of day objects
};
function day() {
var self = this;
self.DayNumber = ko.observable();
self.TodaysDate = ko.observable();
self.Name = ko.observable();
self.Workouts = ko.observableArray(); // a list of workout objects
self.addWorkout = function() {
var wrk = new workout();
wrk.Type = "Workout " + workoutNumber++;
self.Workouts.push(wrk);
};
self.removeWorkout = function() {
// 'this' should represent the item that originated the call (a workout) Not the case...
self.Workouts.remove(this);
};
};
function workout() {
this.Type = ko.observable(); //need to figure out what/how to handle enums
this.WarmUp = ko.observableArray(); // a list of intervals
this.Main = ko.observableArray(); // a list of intervals
this.CoolDown = ko.observableArray(); // a list of intervals
this.Status = ko.observable();
this.Completed = ko.observable();
};
function interval() {
this.timeValue = ko.observable();
this.timeUnit = ko.observable();
this.rpeUnits = ko.observable();
this.heartRateZone = ko.observable();
this.description = ko.observable();
this.distanceValue = ko.observable();
this.distanceUnit = ko.observable();
};
});
Мое мнение:
<div class="container">
<div class="page-header">
<h2>@ViewBag.HeaderText</h2>
</div>
<div class="panel panel-default">
<div class="panel-heading">
<h3>Plan Summary</h3>
</div>
<div class="panel-body">
<div id="NewPlanForm" class="form-horizontal">
@Html.AntiForgeryToken()
@Html.HiddenFor(model => model.ID)
<div class="form-group">
@Html.LabelFor(model => model.Name, new { @class = "control-label col-md-3" })
<div class="col-md-9">
@Html.KnockoutTextBoxFor(model => model.Name, new { @class = "form-control" })
@Html.ValidationMessageFor(model => model.Name)
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.Author, new { @class = "control-label col-md-3" })
<div class="col-md-9">
@Html.KnockoutTextBoxFor(model => model.Author, new { @class = "form-control" })
@Html.ValidationMessageFor(model => model.Author)
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.ShortDescription, new { @class = "control-label col-md-3" })
<div class="col-md-9">
@Html.KnockoutTextBoxFor(model => model.ShortDescription, new { @class = "form-control" })
@Html.ValidationMessageFor(model => model.ShortDescription)
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.LongDescription, new { @class = "control-label col-md-3" })
<div class="col-md-9">
@Html.KnockoutTextAreaFor(model => model.LongDescription, new { @class = "form-control" })
@Html.ValidationMessageFor(model => model.LongDescription)
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.Discipline, new { @class = "control-label col-md-3" })
<div class="col-md-9">
@Html.KnockoutTextBoxFor(model => model.Discipline, new { @class = "form-control" })
@Html.ValidationMessageFor(model => model.Discipline)
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.Level, new { @class = "control-label col-md-3" })
<div class="col-md-9">
@Html.KnockoutTextBoxFor(model => model.Level, new { @class = "form-control" })
@Html.ValidationMessageFor(model => model.Level)
</div>
</div>
</div>
<div class="pull-right">
<div id="btnSavePlan" class="btn btn-primary">Save Plan</div>
</div>
</div>
</div>
</div>
<div id="SchedulePanel" class="panel panel-default">
@Html.HiddenFor(model => model.ID)
<div class="panel-heading">
<h3>Plan Schedule</h3>
</div>
<div class="panel-body">
<div class="pull-right">
<input id="numWeeks" type="text" class="form-control input-sm" placeholder="number"/>
<a id="btnAddWeek" class="btn btn-primary" data-bind="click: addWeek">Add Week(s)</a>
</div>
<div id="ScheduledInstructions">
Click the Add Week button to get started adding workouts to your schedule
</div>
<hr />
<div id="weeks" data-bind="template: { name: 'weekTemplate', foreach: Schedule}">
</div>
</div>
</div>
<script id="weekTemplate" type="text/html">
<div style=" margin-left: auto; margin-right: auto; ">
<h4 data-bind="text: Name"></h4>
<div data-bind="id: weekName, template: { name: 'dayTemplate', foreach: Days }" >
</div>
</div>
</script>
<script id="dayTemplate" type="text/html">
<div class="dayBuilder">
<span data-bind="text: DayNumber"></span>
<div data-bind="id: dayName, template: { name: 'workoutTemplate', foreach: Workouts }" >
</div>
<div class="addWorkout">
<span class="glyphicon glyphicon-plus" data-bind="click: addWorkout" title="Add Workout"></span>
</div>
</div>
</script>
<script id="workoutTemplate" type="text/html">
<div class="workout">
<span data-bind="text: Type"></span>
<span class="glyphicon glyphicon-remove pull-right" data-bind="click: $parent.removeWorkout"></span>
</div>
</script>
Brilliant! Не поймал, что нокаут уже пропустил элемент с кликом. Спасибо Энтони! –