Я создал пользовательскую директиву для рендеринга слайдера для вопроса (по существу, обертывания jquery ui slider). Директива принимает ngModel и обновляет ее, когда пользователь использует слайдер, и к родительской модели прикрепляется $ watch (ngModel, переданный директиве, является только частью родительской модели). Директива имеет несколько экземпляров на странице.Несколько экземпляров пользовательской директивы, путаница с ngModel
Я столкнулся с проблемой с часами, так как кажется, что часы всегда возникают по последнему вопросу на странице. Так, например, страница с 10 вопросами, используя слайдер на вопросе 1, вызывает триггеры последнего вопроса (вопрос 10). Я считаю, что проблема имеет какое-то отношение к директивам/изолированной сфере действия и/или функции часов, но я не могу ее решить.
this.app.directive('questionslider',() => {
var onChangeEvent = (event, ui) => {
updateModel(ui.value);
};
var onSlideEvent = (event, ui) => {
updateUi(event, ui);
};
var updateUi = (event, ui) => {
$(ui.handle).find(".ff-handle-glyph > div").css("top", (ui.value) * - 10);
}
var updateModel = (newValue) => {
// find value in values list...
angular.forEach(isolatedScope.model.PossibleValues, function(value) {
if (parseInt(value.Name) === newValue) {
isolatedScope.$apply(function() {
isolatedScope.model.Value = value;
});
}
});
};
var isolatedScope: any;
return {
restrict: 'AE',
replace: true,
template: '<div></div>',
scope: {
model: '=ngModel',
},
link: function(scope, element, attrs, ctrl) {
isolatedScope = scope;
scope.$watch(ngModelCtrl, function() {
// use provided defaultValue if model is empty
var value = isolatedScope.model.Value === null ? isolatedScope.model.DefaultValue : isolatedScope.model.Value;
element.slider({
min: 0,
max: isolatedScope.model.PossibleValues.length,
value: value.Name,
change: onChangeEvent,
slide: onSlideEvent
});
}
}
};
};
код, чтобы добавить часы в контроллере
this.$scope.questions.forEach(function(question) {
this.$scope.$watch(
function() { return question; },
function(newVal, oldVal) { this.updateQuestion(newVal, oldVal) },
true
);
});
UpdateQuestion функции (теперь просто выводит текущий вопрос)
function updateQuestion(newVal, oldVal) {
// prevent event on initial load
if (newVal === oldVal) {
return;
}
console.log(newVal);
}
В нг-повтор разметки инстанцировании questionsliders
<div data-ng-repeat="question in Questions">
<h4>{{question.QuestionText}}</h4>
<p>{{question.RangeMinText}}</p>
<questionslider ng-model="question"></questionslider>
<p>{{question.RangeMaxText}}</p>
</div>
Вопрос JSON будет выглядеть следующим образом
{
"DefaultValue": {
"Id": "5",
"Name": "5"
},
"Id": "1",
"IsAnswered": false,
"PossibleValues": [
{
"Id": "1",
"Name": "1"
},
{
"Id": "2",
"Name": "2"
},
{
"Id": "3",
"Name": "3"
},
{
"Id": "4",
"Name": "4"
},
{
"Id": "5",
"Name": "5"
},
{
"Id": "6",
"Name": "6"
},
{
"Id": "7",
"Name": "7"
},
{
"Id": "8",
"Name": "8"
},
{
"Id": "9",
"Name": "9"
},
{
"Id": "10",
"Name": "10"
}
],
"QuestionText": "hows it haning?",
"RangeMaxText": "not good",
"RangeMinText": "Very good",
"Type": 0,
"Value": null
}
],
"Title": "Question title",
"Type": 0
}
Так вопрос не является, независимо от того, какой вопрос я обновляю с директивой слайдера, это всегда последний на странице перешла в updateQuestion.
ОБНОВЛЕНИЕ Я пробовал использовать $ watchCollection, но ничего не срабатывает.
this.$scope.$watchCollection(
'questions',
function (newVal, oldVal) {
// prevent event on initial load
if (newVal === oldVal) {
return;
}
for (var i = 0; i < newVal.length; i++) {
if (newVal[i] != oldVal[i]) {
this.$log.info("update : " + newVal.Id);
}
}
}
);
Я также попытался с
function() { return questions; }
как первые выражения. Еще не повезло.
Возможно, использование индивидуальных контроллеров для каждого вопроса является моим единственным вариантом, но, похоже, это обходное решение.
UPDATE Так я попытался использовать отдельные контроллеры для каждого вопроса, добавив часы на каждый вопрос в контроллере, и странное дело в том, что даже это воспроизводя тот же сценарий. Это еще последний вопрос на странице, переданной в функцию часов.
разметки
<div data-ng-repeat="question in Questions" data-ng-controller="QuestionInstanceController">
<h4>{{question.QuestionText}}</h4>
<p>{{question.RangeMinText}}</p>
<questionslider ng-model="question"></questionslider>
<p>{{question.RangeMaxText}}</p>
</div>
Код контроллера
app.controller('QuestionInstanceController', function($scope) {
console.log($scope.question); // outputs correct question here!
$scope.$watch(
function() { return $scope.question; },
function(newValue, oldValue) {
console.log(newValue); // always outputs last question on page
},
true);
}
}
Он должен иметь что-то делать с моей пользовательской директивы, я как-то я перезаписывать предыдущие случаи, когда наличие нескольких экземпляров на странице?
Вы можете поставить несколько образцов с точки зрения HTML также? –
Я бы также предположил, что присвоение значения в изолированной области действия директивы «ngModel» находится в плохом состоянии и запутанно. –
Привет, Майкл, я добавил разметку. Я думал, что ngModel была лучшей практикой для такого рода, потому что его что-то обновляемое, но это не потому, что это изолированная область, это правильно? – morteng