как использовать внешнюю переменную в директиве angularjs?

Я хочу изменить значение ng-model (степень) на id (степень_ид) в моем шаблоне следующим образом

<md-select flex class="md-select-form" ng-model="education.degree" placeholder="Degree" save-id required-param="{{education.degree_id}}">
 <md-option ng-value="degree" ng-repeat="degree in ['High School', 'Associates Degree', 'Bachelor Degree', 'Masters Degree', 'M.B.A', 'M.D', 'Ph.D', 'other']">{{degree}}</md-option>
</md-select>

Я использовал директиву (save-id) для этого синтаксического анализа в моем контроллере, и я вытащил данные службы степени и привязал соответствующий идентификатор. Код следующий

    .directive('saveId', function(Profile){
        return {
            require: 'ngModel',
            scope: {
                requiredParam:'@'
            },        
            link: function(scope, element, attrs, ngModel) {
                console.log("initial loading");
                // view --> model (change to string)            
                ngModel.$parsers.push(function(viewValue){
                    var id = -1;
                    var keepGoing = true;                
                    Profile.getDegreeList().then(function(data) {
                        angular.forEach(data, function(ob){
                            if(keepGoing) {
                                if(ob.degree == viewValue){
                                    id = ob.degree_id;
                                    keepGoing = false;
                                }
                            }
                        });
                        //console.log(id); // it gives updated value
                    });
                    console.log(id); // it gives -1       
                    return id;

                });

            }
        };
    })

Я обновил значение модели, как указано выше, проблема в том, что в пределах доступно только обновленное значение.

Профиль.getDegreeList(){ }

Из этой функции значение равно -1, что здесь не так? Пожалуйста, дайте мне решения ??


person user3391137    schedule 07.12.2015    source источник
comment
Что именно вы пытаетесь сделать? Я думаю, что странно, что ваша директива вернет что-то в своем блоке link.   -  person Spikee    schedule 07.12.2015
comment
Не могли бы вы предоставить Plunk (или другой источник) того, чего вы пытаетесь достичь? Трудно понять, что вы пытаетесь сделать.   -  person Spikee    schedule 07.12.2015
comment
Рассмотрим этот планк: plnkr.co/edit/oDHyEp4YNlgEGpdZrsvp?p=preview Что еще нужно сделать? вы требуете?   -  person Spikee    schedule 07.12.2015
comment
на самом деле мне нужно изменить это значение на id bro   -  person user3391137    schedule 07.12.2015
comment
Какое значение вы имеете в виду? Можно ли разветвить этот Plunk и добавить к нему то, что вам нужно (не обязательно работать)?   -  person Spikee    schedule 07.12.2015
comment
мне нужно изменить значение ng-модели на выбранный идентификатор элемента, чем сохранить его как это значение, поэтому я использовал каталог в своем почтовом индексе, братан   -  person user3391137    schedule 07.12.2015
comment
я использовал для этого ngModel.$parsers.push(function(viewValue){})   -  person user3391137    schedule 07.12.2015
comment
Извините, я не понимаю требований, которые вы упомянули, не могли бы вы пояснить? Сейчас у меня сложилось впечатление, что вы излишне усложняете ситуацию.   -  person Spikee    schedule 07.12.2015
comment
Давайте продолжим обсуждение в чате.   -  person user3391137    schedule 07.12.2015
comment
см. эту ссылку stackoverflow.com/questions/34132574/   -  person user3391137    schedule 07.12.2015


Ответы (2)


Это потому, что ваш вызов Profile.getDegreeList() является асинхронным.

console.log(id) за пределами блока getDegreeList выполняется немедленно, что означает, что он регистрирует определенное значение -1.

console.log(id) внутри блока getDegreeList работает, потому что в этот момент данные загружаются.

Вам следует работать с обещаниями ($q).

Я не уверен, что вы пытаетесь сделать, но, проще говоря, сработает следующее: можно легко использовать атрибут значения опции, чтобы присвоить значение идентификатора раскрывающемуся списку, а не проходить через директиву.

 <select ng-model="education.degree.id" id="degreeList">
    <option 
      value="{{degree.id}}" 
      ng-selected="{{education.degree == degree}}" 
      ng-repeat="degree in degrees">
        {{degree.name}}
    </option>
  </select>

И в вашем контроллере (например)

 .controller("myController", [
  "$scope",
  "$http",
  function($scope, $http){
    var self = {};

    $scope.education = {
      degree: {
        id: -1,
        name: ""
      }
    };

    $scope.degrees = 
    [
      {
        id: 1,
        name: 'High School'
      }, 
      {
        id: 2,
        name: 'Associates Degree'
      }, 
      {
        id: 3,
        name: 'Bachelor Degree'
      }, 
      {
        id: 4,
        name: 'Masters Degree'
      }, 
      {
        id: 5,
        name: 'M.B.A'
      }, 
      {
        id: 6,
        name: 'M.D'
      }, 
      {
        id: 7,
        name: 'Ph.D'
      }, 
      {
        id: 8,
        name: 'other'
      }];
  }]);
person Spikee    schedule 07.12.2015
comment
Обновлен скрипт для использования $scope.id. Это самое простое решение, не зная точно, чего вы пытаетесь достичь. - person Spikee; 07.12.2015
comment
$scope означает, что это изолированная область действия директивы no? - person user3391137; 07.12.2015
comment
Да, если это не параметр, предоставленный directive привязкой в ​​его scope определении. - person Spikee; 07.12.2015
comment
я пробовал это, братан, он обновляет значение, но обновляет неправильно, это означает, что обновляет значение, которое ранее было выбрано в раскрывающемся списке. - person user3391137; 07.12.2015
comment
Если вы используете это так: scope: { id: '=', requiredParam:'@' } <myDirective id="model.someId"></myDirective> ? Используя приведенный выше сценарий, ваша внешняя переменная `model.someId' должна автоматически обновляться посредством двусторонней привязки. - person Spikee; 07.12.2015
comment
‹myDirective id=model.someId›‹/myDirective› это что? это мой ‹md-select›? - person user3391137; 07.12.2015
comment
Я проглядел это раньше, но поскольку ваша директива называется saveId, она <save-id id="model.someId">. - person Spikee; 07.12.2015
comment
я использовал в качестве атрибута, например ‹md-select save-id›‹/md-select›, вы говорите прикрепить идентификатор, например ‹md-select save-id id=model.someId›‹/md-select› rght ? - person user3391137; 07.12.2015
comment
Как расширение атрибута, да! Должно сработать. Примечание: если md-select тоже принадлежит вам, я бы встроил его непосредственно в него, а не расширил ваш собственный тег (если, конечно, вас не заставят другие требования). - person Spikee; 07.12.2015
comment
по-прежнему обновляет неправильное значение (обновляет значение, которое ранее было выбрано в раскрывающемся списке) - person user3391137; 07.12.2015
comment
Не могли бы вы предоставить планк (или что-то еще) для полного образца? - person Spikee; 07.12.2015
comment
кажется, как вы сказали, проблема связана с асинхронным выполнением Profile.getDegreeList(). есть ли у вас способ (контекст) выполнить код console.log(id) после успешного выполнения обещания? - person user3391137; 07.12.2015
comment
Мой ответ выше сделает это. Я не понимаю, зачем вам нужно связывать промис, потому что было бы странно возвращать что-либо в .link. Если вам нужно что-то вернуть, вы должны вместо этого поместить это в service. - person Spikee; 07.12.2015
comment
потому что мне нужно взять идентификаторы для выпадающих меню из службы, поэтому я вытаскиваю службу - person user3391137; 07.12.2015
comment
Если я вас правильно понял, то в таком случае он должен быть в controller. Либо напрямую, либо потребляя service. - person Spikee; 07.12.2015
comment
Фактическая вещь, которую мне нужно сделать, это, как я уже упоминал в этом посте, я хочу изменить значение модели ng-модели как идентификатор из строки. Модель ng содержит строковое значение drp-down, когда пользователь выбирает и сохраняет раскрывающийся список формы. должен дать идентификатор, чем имя. для этого я использовал эту директиву, чтобы изменить значение модели - person user3391137; 07.12.2015
comment
Я думаю, вы слишком все усложняете, поэтому я и прошу образец. Так легче предлагать конкретные исправления. - person Spikee; 07.12.2015
comment
И чтобы определить идентификатор выбранного элемента, я вытащил эту службу, которая содержит значения идентификатора и имени элемента. - person user3391137; 07.12.2015

Profile.getDegreeList() возвращает обещание, которое оценивается асинхронно. Вы регистрируете некоторый код, который выполняется, когда обещание разрешено. В этом коде устанавливается идентификатор. Тем не менее, линия

console.log(id);

который сразу следует за созданием обещания, выполняется до того, как обещание будет разрешено.

Если вы хотите продолжить обработку идентификатора или передать его другой функции, вы должны сделать это в обещании. Это означает, что линия

ngModel.$parsers.push(...) 

должен быть втянут в функцию, которая вызывается при разрешении промиса (т. е. функция, переданная then())

person lex82    schedule 07.12.2015
comment
Да, братан, я определил проблему .. однако я хочу вернуть идентификатор в конце ngModel.$parsers.push(). как решить? - person user3391137; 07.12.2015
comment
кажется, как вы сказали, проблема связана с асинхронным выполнением Profile.getDegreeList(). есть ли у вас способ (контекст) выполнить код console.log(id) после успешного выполнения обещания? - person user3391137; 07.12.2015
comment
Функция, переданная методу .then() вашего обещания, является единственным контекстом, в котором вы можете работать со значением. Вы не можете заблокировать, пока обещание не будет разрешено. - person lex82; 07.12.2015