Как вызвать ng-change на md-select при изменении модели?

#javascript #angularjs #angularjs-directive #angular-material

#javascript #angularjs #angularjs-директива #angular-материал

Вопрос:

Я использую md-select и должен запускать определенный код при изменении значения (создание селектора страны / состояния). У меня все работает нормально, когда я меняю значение с помощью элемента управления, но мне также нужно, чтобы элементы управления правильно отражали значения при изменении модели из кода. Я использую ng-change для запуска кода изменения (требуется ng-change, поскольку пользователь может изменять значение с клавиатуры, не нажимая на него). Проблема в том, что при изменении значения из кода событие не запускается. Чтобы еще немного усложнить ситуацию, md-selects работает в директиве, позволяющей мне использовать настройку в нескольких местах.

Вот мой шаблон директивы:

 <md-input-container class="md-block">
    <label>Country</label>
    <md-select name="country" ng-model="countryState.countryModel" ng-change="countryState.onCountrySelected()">
        <md-option ng-repeat="country in countryState.countries" ng-value="country.itemId">
            {{ country.name | translate }}
        </md-option>
    </md-select>
</md-input-container>

<md-input-container class="md-block">
    <label>State</label>
    <md-select name="state" ng-model="countryState.stateModel" ng-disabled="countryState.countryModel == null">
        <md-option ng-repeat="state in countryState.states" ng-value="state.itemId">
            {{ state.name | translate }}
        </md-option>
    </md-select>
</md-input-container>
  

Вот код директивы:

 angular.module('myapp.shared')

    .directive('countryStateInput', [function () {
        return {
            restrict: 'E',
            templateUrl: 'app/shared/inputs/countryState/country-state-input.directive.html',
            transclude: false,
            scope: {
                coordsForm: '=',
                countryModel: '=',
                stateModel: '='
            },
            bindToController: true,
            controllerAs: 'countryState',
            controller: ['$scope', '$document', 'OptionService', function($scope, $document, OptionService) {
                var ctrl = this;

                // Properties
                ctrl.countries = null;
                ctrl.states = [];
                ctrl.selectedCountryIndex = null;

                ctrl.onCountrySelected = function() {
                    // Get the index of the country
                    for (var i = 0; i < ctrl.countries.length; i  ) {
                        if (ctrl.countryModel === ctrl.countries[i].itemId) {
                            // If a different country was chosen, clear the selected state
                            if (i !== ctrl.selectedCountryIndex) {
                                ctrl.stateModel = null;
                                angular.copy(ctrl.countries[i].states, ctrl.states);
                            };

                            // Save the index of the selected country
                            ctrl.selectedCountryIndex = i;
                            return;
                        }
                    }
                };

                // Initialization
                var initialize = function () {
                    OptionService.getCountries().then(
                        function (result) {
                            ctrl.countries = resu<
                        });
                };

                (function () {
                    $document.ready(function () {
                        initialize();
                    })
                })();
            }]
        }
    }]);
  

Вот пример использования:

 <country-state-input country-model="app.location.countryId" state-model="app.location.stateId" input-form="locationsForm"></country-state-input>
  

И OptionService.getCountries() возвращает что-то вроде этого (списки состояний сокращаются):

 [
    {
        "itemId": 1,
        "name": "CA",
        "states": [
            {
                "itemId": 1,
                "name": "CA_ON",
                "abbreviation": "ON"
            },
            {
                "itemId": 2,
                "name": "CA_QC",
                "abbreviation": "QC"
            }
        ]
    },
    {
        "itemId": 2,
        "name": "US",
        "states": [
            {
                "itemId": 14,
                "name": "US_AL",
                "abbreviation": "AL"
            },
            {
                "itemId": 15,
                "name": "US_AK",
                "abbreviation": "AK"
            }
        ]
    }
]
  

По сути, я пытаюсь выяснить, есть ли способ запустить onCountrySelected, который будет охватывать все 3 варианта использования.

Ответ №1:

Вы могли бы использовать $scope. $watch

 $scope.$watch(
   function valueGetter(){
      return smth;
   },
   function onChange(newSmth, oldSmth){
   }
)
  

Комментарии:

1. Спасибо, Валерий! На самом деле я пробовал смотреть на ctrl.CountryModel, который не работал, но ввод функции valueGetter там работал.