The directive isn't responding to changes in the Angular scope.watch function

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>

Answer №1

After investigating, I discovered the solution. It appears that the line below is not functioning as expected

scope.$watch(scope.sourceList, (newVal) => {

By modifying it to the following, the issue was resolved

scope.$watch('sourceList', (newVal) => {

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Verifying child attributes within a collection using AngularJS expressions

Is there a way to write an angular expression that can check each child item in a list and return true if any child has a specific property value? My issue involves a chart legend generated by an ng-repeat expression. I want the wrapping element to be sho ...

Refreshing the View in Ionic and AngularJS Using Controller UpdatesIn this tutorial, we will

As a newcomer to both Ionic and Angularjs, I am currently in the process of developing a simple Ionic app. The main functionality involves displaying a list of classes (sessions), allowing users to book or cancel a class by clicking on an icon, and updatin ...

The specified type 'x' cannot be assigned to the type 'x'. Error code: 2322

I encountered an issue with the code in @/components/ui/billboard.tsx file import { Billboard } from "@/types" interface BillboardProps { data: Billboard; }; const BillboardComponent: React.FC<BillboardProps> = ({ data }) => ...

'The signatures of each of these values are not compatible with one another.' This error occurs when using find() on a value that has two different array types

Here's the code snippet I'm attempting to run within a TypeScript editor: type ABC = { title: string } type DEF = { name: string } type XYZ = { desc: ABC[] | DEF[] } const container: XYZ = { desc: [{title: & ...

Implement a personalized callback function for a specific resource

Currently, I am using angularjs version 1.1.5 and have a service provider for a resource. In one specific use case, the returned response needs to be reprocessed and some information normalized. Although this is a special case, the resource is utilized thr ...

Tally the quantity of items within a JSON array

When using the GET method to access a JSON file, my code looks like this: $scope.train = function () { var url = 'http://localhost/heart/api/restApiController/dataset.json'; $http({ method: 'GET&apo ...

Guide to eliminating text following a space within a string in Angular 8

Having trouble trying to capitalize the first letter after an underscore in a string using Angular 8. Can anyone help me find a solution? app.component.ts: let content="power_managment 0vol"; alert(content.split( ).[0]); // desired output: "powerManagmen ...

Downloading multiple files using checkboxes in AngularJS is a convenient feature that enhances

I am new to working with AngularJS and I have encountered an issue. I have a checkbox that allows users to select multiple files for download. After selecting the checkboxes, the user can click on a button to initiate the download process. However, I am fa ...

What is the best way to show the previous month along with the year?

I need help with manipulating a date in my code. I have stored the date Nov. 1, 2020 in the variable fiscalYearStart and want to output Oct. 2020. However, when I wrote a function to achieve this, I encountered an error message: ERROR TypeError: fiscalYear ...

Steps to insert a style tag into the head using an AngularJS directive

Greetings! Users have the option to choose between printing reports in landscape or portrait format. I am interested in finding out if it is feasible to incorporate the following code snippet into the header of a web document using an AngularJS directive. ...

Recent Google algorithm changes impact websites built on AngularJS and JavaScript

Exciting news from Google today (May 28, 2014) - JavaScript content will now be rendered by the Googlebot itself! This means there's no need to worry about serving pre-rendered pages just for crawling purposes. You can find out more details on this an ...

Guide to resolving the issue of error Type 'void[] | undefined' cannot be assigned to type 'ReactNode'

I am attempting to map the data Array but I am encountering an error: Type 'void[] | undefined' is not assignable to type 'ReactNode'. Can someone please assist me in identifying what I am doing wrong here? Below is the code snippet: i ...

`Upkeeping service variable upon route alteration in Angular 2`

Utilizing a UI service to control the styling of elements on my webpage is essential. The members of this service change with each route, determining how the header and page will look. For example: If the headerStyle member of the service is set to dark ...

The Relationship Between Typing Variables and Generic Types in Functions

I need help implementing a specific function type: type TestType<T extends HTMLElement> = (input: T) => React.Ref<T>; I have a variable that I want to be typed with the above type for strict type guarantees on the return type: const Test ...

Steer clear of using sourceMap files

Here is the content of my tsconfig.json file: { "compilerOptions": { "target": "es5", "module": "commonjs", "moduleResolution": "node", "sourceMap": true, "emitDecoratorMetadata": true, "experimentalDecorators": true, "remove ...

Unit Testing Angular: Passing FormGroupDirective into a Function

I am currently writing unit tests for a function that takes a parameter of type FormGroupDirective. I have been able to test most of the logic, but I'm unsure about what to pass as a parameter when calling the resetForm() function. Here is the code sn ...

Unable to access global functions in Typescript

My current setup involves using cloudflare workers with miniflare. I have structured a bindings.d.ts file as follows: export interface Bindings { ENV: string MYSQL_URL: string JWT_SECRET: string JWT_ACCESS_EXPIRATION_MINUTES: number JWT_REFRESH_E ...

Stop automatic selection of the last value in ng-options using AngularJS

I'm facing an issue related to AngularJS. The problem I'm encountering is that... In my code, there are two select elements. Whenever I choose an option from the first select, an Ajax call is made using ng-change to populate the second select ba ...

Received an unexpected argument count of 1 instead of the expected 0 while passing a function as a prop to a child component

I transferred the deleteImgfunc function from the insertFarmDiaryDetail component to the InsertFarmDiarySubPage component, which acts as a child component. DeleteImgfunc is a parameter-receiving function. Despite creating an interface and defining paramet ...

`The modal window fails to appear when triggered by ng-click`

I'm attempting to implement a modal popup window in my Angular application. Despite displaying the names, clicking on them does not trigger the modal to show up. Here's the code snippet: HTML: <div ng-app="app"> <div ng-repeat="cus ...