как да използвам външна променлива в директивата angularjs?

Искам да променя стойността на ng-model(degree) на id(degree_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;

                });

            }
        };
    })

Актуализирах стойността на модела, както беше споменато по-горе, проблемът е, че само актуализираната стойност е налична в рамките

Profile.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-model на избран item'id, отколкото да я запазя като тази стойност, затова използвах директорията в моя пощенски код, брато   -  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).

Не съм сигурен какво се опитвате да направите, но просто казано, следното би свършило работа: можете лесно да използвате атрибута стойност на опцията, за да присвоите стойността на id към падащото меню, вместо да преминавате през директива.

 <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 означава кой е изолиран обхват на директива не? - 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
Като разширение на атрибут, да! Трябва да работи. Sidenote, ако md-select също е ваш, бих го вградил директно в това, вместо да разширя вашия собствен етикет (освен ако други изисквания не ви налагат, разбира се). - person Spikee; 07.12.2015
comment
все още актуализира грешна стойност (актуализира стойността, която преди това е избрана в падащото меню) - person user3391137; 07.12.2015
comment
Бихте ли предоставили Plunk (или нещо друго) за пълна проба? - 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-model като id от низ, моделът 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