I am facing an issue with my Angular directive that monitors a list and generates a custom select when the list is modified. While it works perfectly on one page, it fails to work on another page. I am unable to determine why, but it seems like the watch function is not detecting changes in the list.
Here is a reproduction of the error - http://codepen.io/jagdipa/pen/Ramjez. Can someone kindly assist me with this problem?
angular.module('MyApp',['ngMaterial', 'ngMessages', 'material.svgAssetsCache'])
.controller('AppCtrl', function($scope) {
$scope.clearValue = function() {
$scope.myModel = undefined;
};
$scope.save = function() {
alert('Form was valid!');
};
var Titles =[{"Title":"Mr"},{"Title":"Master"},{"Title":"Miss"},{"Title":"Mrs"}];
$scope.titles = Titles;
});
module MyApp.Directives {
interface TcSelectListScope extends ng.IScope {
sourceList: any[];
sourceListKey: string;
sourceListValue: string;
}
export class TcSelectListController {
static $inject = [];
constructor() {
}
}
export class TcSelectList {
public restrict = "A";
public require = ["ngModel", "^form", '^^mdInputContainer', "select"];
public controller = TcSelectListController;
public controllerAs = 'selectController';
public scope = {
sourceList: "="
}
constructor(private $compile: ng.ICompileService) {
}
public compile(tElement, tAttributes) {
var $compile = this.$compile;
var _cacheService = this.cacheService;
return function postLink(scope, element, attrs, controller) {
var ngModelCtrl = controller[0];
var mdInputContainerCtrl = controller[2];
var selectCtrl = controller[3];
console.log(selectCtrl);
/*if (scope.sourceList == undefined)
{
scope.sourceList = [];
}*/
scope.$watch(scope.sourceList, scope.onModelChanged, true);
//scope.$watchCollection(scope.sourceList, scope.onModelChanged);
scope.onModelChanged = () => {
console.log('tc select list directive 2');
console.log(scope.sourceList);
if (attrs.sourceListKey == undefined) {
throw ("The source-list-key needs to be defined for tc-select-list");
}
if (attrs.sourceListValue == undefined) {
throw ("The source-list-value needs to be defined for tc-select-list");
}
var html = undefined;
html = buildSelect();
html = markSelected(html);
element.append(html);
}
element.on("click", function () {
mdInputContainerCtrl.setHasValue(true);
});
element.bind("blur", function () {
if (ngModelCtrl.$viewValue == undefined) {
mdInputContainerCtrl.setHasValue(false);
}
});
element.bind("change", function () {
mdInputContainerCtrl.setHasValue(true);
});
function buildSelect() {
var html = ``;
angular.forEach(scope.sourceList, (val, index) => {
var itemKey = scope.sourceList[index][attrs.sourceListKey];
var itemValue = scope.sourceList[index][attrs.sourceListValue];
var selected = ``;
html += `<option label="` + itemValue +
`" value="` + itemKey +
`" ` + selected +
` >` + itemValue + ` < /option>`;
});
return html;
}
function markSelected(html) {
if (ngModelCtrl.$modelValue != undefined && ngModelCtrl.$modelValue != null) {
html = html.replace(`value="` + ngModelCtrl.$modelValue + `"`,
`value="` + ngModelCtrl.$modelValue + `" selected`)
}
return html
}
}
}
static factory() {
var directive = ($compile, cacheService) => new TcSelectList($compile, cacheService);
directive.$inject = ["$compile"];
return directive;
}
}
angular.module("MyApp").directive("tcSelectList", TcSelectList.factory());
}
<div ng-controller="AppCtrl" layout="column" layout-align="center center" style="min-height: 300px;" ng-cloak="" class="selectdemoValidations" ng-app="MyApp">
<form name="myForm">
<p>Note that invalid styling only applies if invalid and dirty</p>
<md-input-container class="md-block">
<label>Favorite Number</label>
<md-select name="myModel" ng-model="myModel" required="">
<md-option value="1">One 1</md-option>
<md-option value="2">Two</md-option>
</md-select>
<div class="errors" ng-messages="myForm.myModel.$error" ng-if="myForm.$dirty">
<div ng-message="required">Required</div>
</div>
</md-input-container>
<div layout="row">
<md-button ng-click="clearValue()" ng-disabled="!myModel" style="margin-right: 20px;">Clear</md-button>
<md-button ng-click="save()" ng-disabled="myForm.$invalid" class="md-primary" layout="" layout-align="center end">Save</md-button>
</div>
<md-input-container class="no-errors">
<label>{{translations["Title"]}}</label>
<div class="tc-select">
<select name="title"
tc-select-list
ng-model="myModel.Title"
source-list="titles"
source-list-key="Title"
source-list-value="Title"></select>
</div>
</md-input-container>
<br/>
{{titles}}
<br/>
Title = {{myModel.Title}}
</forms>
</div>