2015-08-06 2 views
1

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

Semesters: ko.observableArray([ 
    { 
     semesterName: "Fall", 
     semesterCode: "300", 
     PlannedCourses: ko.observableArray([]), 
     totalCredits: ko.computed(function(){ 
      var total = 0; 
      ko.utils.arrayForEach(this.PlannedCourses, function (course) { 
       total += course.MinHours(); 
      }); 

      return total; 
     }), 
    }, 
    ... 

То, что я пытаюсь сделать, это, в переменной totalCredits, я пытаюсь перебирать массив PlannedCourses и получить переменную MinHours для каждого элемента и добавить их вместе в общей переменной. Затем я возвращаю его в элемент totalCredits в массиве Semesters. Проблема, с которой я сталкиваюсь, заключается в получении переменной PlannedCourses в части ko.utils.arrayForEach. Я получаю undefined на нем, и я не уверен, почему. Я думаю, что это простая синтаксическая ошибка, но я не вижу, что случилось.

Наблюдаемый массив PlannedCourses - это динамический объект, который правильно получает список PlannedCourses. Он определяется в контексте самого себя, но я не передаю его в вычисляемую функцию totalCredits должным образом.

Надеюсь, это достаточно ясно. Спасибо за помощь!

Примечание: вся остальная часть кода работает по назначению. Единственной частью, которая не работает, является вычисляемая функция totalCredits. Я не уверен, что что-то внутри ko.utils.arrayForEach работает, поскольку я не смог зайти так далеко.

ответ

4

Вы будете нуждаться чтобы изменить способ заселить свой Semesters наблюдаемой массив использовать функцию конструктора для того, чтобы получить ссылку на нужный объем для this:

function semester(name, code) { 
    this.Name = name; 
    this.Code = code; 
    this.PlannedCourses = ko.observableArray([]); 
    this.totalCredits = ko.computed(function(){ 
     var total = 0; 
     ko.utils.arrayForEach(this.PlannedCourses(), function (course) { 
      //Note the change to "this.PlannedCourses()" above to get the underlying array 
      total += course.MinHours(); 
     }); 

     return total; 
    }, this); //now we can pass "this" as the context for the computed 
} 

Посмотрите, как мы можем теперь перейти в n для второго аргумента для ko.computed для использования в качестве контекста для this во внутренней функции.Для получения дополнительной информации см. Документы нокаута: Managing 'this'.

Вы затем создать новые экземпляры semester при заполнении вашего массива:

Semesters: ko.observableArray([ 
    new semester("Fall", "300"), 
    new semester(...) 
]); 

Этот подход также означает, что у вас есть последовательный способ создания ваших semester объектов (вычисленный определяется только один раз для одной вещи), а чем возможно включение опечаток и т. д. в любое повторение, которое вы, возможно, первоначально имели.

+0

Это, наверное, лучший подход. Я собираюсь сделать много реструктуризации, но, без сомнения, я должен это делать. Я ценю это. Я пытаюсь включить несколько различных методов viewModel, и это усложняет ситуацию. Сейчас «Semesters» - это элемент, который является частью еще одного массива «Years», который имеет «academwork» и «Semesters», который структурирован так же, как и «Semesters». Если я переработаю оба списка так, как вы указали, это должно сработать. Тем не менее, это займет некоторое время. Я скоро вернусь к вам, если это сработает. Еще раз спасибо! –

+0

Если вы создаете несколько объектов с одинаковыми свойствами/функциями и т. Д., Это будет обычный подход. –

+0

Это сработало. Еще раз спасибо @JamesThorpe. –

0

Объем (это) не то, что вы думаете.

См http://knockoutjs.com/documentation/computedObservables.html

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

Semesters: ko.observableArray([ 
{ 
    semesterName: "Fall", 
    semesterCode: "300", 
    PlannedCourses: ko.observableArray([]), 
    totalCredits: ko.computed(function(){ 
     var total = 0; 
     ko.utils.arrayForEach(this.PlannedCourses, function (course) { 
      total += course.MinHours(); 
     }); 

     return total; 
    }, this), // new context passed in here 
}, 
... 

Делать это проходит в контексте самого элемента массива в вашей вычисленной функции.

Edit: вам может понадобиться для доступа к семестры объекта внутри вас цикла, и добавить какой-нибудь способ для ссылки на текущий элемент:

Semesters: ko.observableArray([ 
{ 
    semesterName: "Fall", 
    semesterCode: "300", 
    PlannedCourses: ko.observableArray([]), 
    totalCredits: ko.computed(function(){ 
     var total = 0; 
     for(var i = 0, len = Semesters().length; i < len; i++) { 
      // check current array item, possibly add an id? 
      if(Semesters()[i].semesterName === "Fall" && 
       Semesters()[i].semesterCode === "300") { 

       ko.utils.arrayForEach(Semesters()[i].PlannedCourses, function (course) { 
        total += course.MinHours(); 
       }); 
       break; // done searching 
      } 
     } 

     return total; 
    }) 
}, 
+1

С учетом того, как объект строится, 'this' даже не будет правильным во внешнем пространстве. –

+0

@JamesThorpe Мои мысли точно –

+0

Хмм, я думаю, вы правы. – dfperry

0

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

totalCredits: ko.computed(function() { 
    // Computation goes here.. 
}, this) 

Другой подход может заключаться в сохранении правильного this в некоторой локальной переменной во время создания объекта (бывший var self = this;, а затем использовать self вместо this.) ,

Однако ko.utils.arrayForEach не работает с наблюдаемыми массивами, но работает на чистых массивах JavaScript, поэтому вы должны разворачивать наблюдаемый массив для доступа к элементам базового массива:

ko.utils.arrayForEach(this.PlannedCourses(), function(course) { 
    // ... 
}); 

// Or 

ko.utils.arrayForEach(ko.unwrap(this.PlannedCourses), function(course) { 
    // ... 
}); 
+0

«Однако ko.utils.arrayForEach не работает с наблюдаемыми массивами, но работает на чистых массивах JavaScript» Я не знал об этом. Спасибо. Я отредактировал свой код, чтобы использовать ko.unwrap и присвоил себе это. Тем не менее, я все еще не уверен в планировании. Позвольте мне взглянуть еще раз и посмотреть, смогу ли я выяснить, что происходит за пределами моей ошибки ... –

Смежные вопросы