2013-09-26 2 views
0

У меня есть различные входы (в том числе директив, которые будут объяснены позже), таких как:свойства использования контроллера/методы в директиве

<input mask-value="ssn" validate="checkSsn"/> 
<input mask-value="pin" validate="checkPin"/> 

Эти свойства в контроллере:

app.controller("Ctrl", ['$scope', function ($scope) { 
    $scope.ssn = ""; 
    $scope.pin = ""; 

    $scope.checkSsn = function() { /* validate $scope.ssn */ }; 
    $scope.checkPin = function() { /* validate $scope.pin */ }; 
}]); 

Наконец, maskValue директивы:

app.directive("maskValue", function() { 
    return function (scope, element, attrs) { 
     /* does some focus/blur magic and string replacement */ 
     scope[attrs.maskValue] = this.value; 
     scope[attrs.validate](); 
    }; 
}); 

Это работает, но это, кажется, как злоупотребления Угловая мне. Вместо этого, было бы более целесообразно использовать изолированный объем, как в:

scope: {validate: "&"} 

Тогда я мог бы использовать scope.validate() вместо scope[attrs.validate](). Однако, с изолированной областью действия Я не могу обновить соответствующее значение в контроллере. Использование {maskValue: "="} не работает, потому что это попытается обновить свойство maskValue родителя, а не определенное значение. Я думаю, что использование {ssn: "="} будет работать, но тогда я должен обновить определенное свойство контроллера, а не устанавливать его как атрибут директивы, который сделает директиву негибкой. По-видимому, использование $parent также не рекомендуется.

Как я могу динамически получить доступ к свойствам контроллера внутри изолированной директивы scope?

EDIT: я не могу использовать ng-model=ssn и т.д. на входах потому что во время событий фокуса/размытия в mask-value изменяется фактическое значение входа. Например, он может стать *****####, но мне нужно сохранить фактическое значение ######### где-то, и контроллер, похоже, является подходящим местом, так как контроллер будет использовать его по другим причинам позже.

+0

Использование области изоляции с '=' свойствами делает именно то, что вы хотите. Почему вы говорите, что это не работает? Не могли бы вы предоставить скрипт Plunker/jsFiddle? –

+0

@MichaelBenford Я подниму его. '=' не работает точно, потому что он обновляет 'maskValue' в контроллере (которого не существует). Я мог бы сделать, например, 'ssn:" = "', но тогда я полагаюсь на определенное значение. Я хочу, чтобы я смог прозрачно обновлять свойство. –

+0

@MichaelBenford. Вы можете видеть, что это работает: http://jsfiddle.net/MmyvX/ - это моя попытка более уклонно (я думаю), используя изолированную область. Это не работает: http://jsfiddle.net/MmyvX/1/ –

ответ

2
<div ng-app=foo> 
    <div ng-controller=Ctrl> 
    {{ssn}} 
    <input mask-value="ssn" validate="checkSsn()"> 

app = angular.module("foo", []); 

app.controller("Ctrl", ['$scope', function ($scope) { 
    $scope.ssn = ""; 
    $scope.checkSsn = function() { console.log($scope.ssn); }; 
}]); 

app.directive("maskValue", function() { 
    return { 
     scope: { 
      validate: "&", 
      maskValue: "=" 
     }, 
     link: function (scope, element, attrs) { 
      element.bind("change", function() { 
       scope.maskValue = this.value; 
       scope.$apply(); 
       scope.validate(); 
      }); 
     }, 
    }; 
}); 

http://jsfiddle.net/bfDqy/

EDIT:

они скажем, бет эр передать выражение, которое вы хотите, чтобы оценить в качестве аргумента $apply из-за некоторых обработки ошибок особенностей Anguular:

var value = this.value; 
scope.$apply(function() { 
    scope.maskValue = value; 
}); 
+0

Это действительно работает! Я немного смущен, почему. Я полагаю, что '=' принимает значение атрибута *, а не имя атрибута для обновления родительскому. Это прекрасно, хотя :) –

+0

согласно документации, '=' устанавливает двухстороннее связывание с моделью родительской области. единственное, что внутри обработчика событий вам нужно вызвать '$ apply', чтобы он знал, что нужно обновлять привязки. – akonsu

+0

Я должен вызвать 'scope. $ Apply()' после '.validate()', а потому, что '.validate()' обновляет область контроллера (в частности, он устанавливает '$ scope.error'. Любой способ избежать этого или это только что ожидаемый? –

0

Мне так жаль, но почему бы не просто сделать:

app = angular.module("foo", []); 

app.controller("Ctrl", ['$scope', function ($scope) { 
    $scope.ssn = ""; 
    $scope.validate = function() { console.log($scope.ssn); }; 
}]); 

app.directive("maskValue", function() { 
    return { 
     link: function (scope, element, attrs) { 
      element.bind("change", function() { 
       scope.validate(); 
      }); 
     }, 
    }; 
}); 

И HTML вроде:

<div ng-app=foo> 
    <div ng-controller=Ctrl> 
     <input ng-model="ssn" mask-value /> 
    </div> 
</div> 
1

Я знаю, что вы уже получили ответ на свой вопрос, но я думаю, что стоит отметить, что, поскольку вы, похоже, выполняете некоторую проверку, вы можете использовать встроенные функции Angular, чтобы сделать это и все еще иметь возможность использовать ng-model.Вот пример:

app.directive("maskValue", function ($parse) { 
    return { 
    restrict: 'A', 
    require: 'ngModel', 
    link: function (scope, element, attrs, ngModel) { 
     if (!ngModel) return; 
     var validator = $parse(attrs.validator)(scope); 

     ngModel.$render = function() { 
     var hasFocus = document.activeElement == element[0]; 
     if (ngModel.$valid || hasFocus) element.val(ngModel.$modelValue) 
     else element.val('#######'); 
     }; 

     element.bind('blur', function() { 
     ngModel.$setValidity('maskValue', validator(this.value)) 
     ngModel.$render(); 
     }); 

     element.bind('focus', function() { 
     ngModel.$render(); 
     }); 
    } 
    }; 
}); 

Эта директива используется NgModelController для того, чтобы работать вместе с ng-model контролировать, как обновляется вид. В этом надуманном примере он просто отображает ########, когда элемент теряет фокус и функция проверки возвращает false. Но когда управление снова сфокусируется, оно будет оказывать реальную ценность, чтобы пользователь мог его изменить. Обратите внимание, что свойство области, связанной с элементом управления, остается неповрежденным, тогда как его представление изменяется в соответствии с состоянием элемента (действительным или недействительным). Вы можете увидеть рабочий пример here.

Смежные вопросы