javascript - personalizadas - Cómo obtener atributos evaluados dentro de una directiva personalizada
directive in angular español (6)
Estoy tratando de obtener un atributo evaluado de mi directiva personalizada, pero no puedo encontrar la forma correcta de hacerlo.
He creado este jsFiddle para elaborar.
<div ng-controller="MyCtrl">
<input my-directive value="123">
<input my-directive value="{{1+1}}">
</div>
myApp.directive(''myDirective'', function () {
return function (scope, element, attr) {
element.val("value = "+attr.value);
}
});
¿Qué me estoy perdiendo?
Las otras respuestas aquí son muy correctas y valiosas. Pero a veces solo desea lo simple: obtener un valor analizado antiguo en la instanciación de directivas, sin necesidad de actualizaciones y sin alterar el alcance del aislamiento. Por ejemplo, puede ser útil proporcionar una carga útil declarativa en su directiva como una matriz u objeto hash en el formulario:
my-directive-name="[''string1'', ''string2'']"
En ese caso, puede cortar a la persecución y simplemente usar un buen angular.$eval(attr.attrName)
básico angular.$eval(attr.attrName)
.
element.val("value = "+angular.$eval(attr.value));
Fiddle trabajo.
Muchas buenas respuestas aquí, pero a veces solo quieres una solución simple, fácil, antigua, jQuery-ish.
Mi solución no maneja los cambios en el DOM. Si el atributo puede cambiar, ¡no uses mi método!
En mi caso, tenía un elemento y necesitaba recuperar el valor de un atributo (rel).
Modelo:
<div ng-repeat="elm in array">
<button class="poi-lines-show" rel="li-{{$index}}">button-text</button>
</div>
En mi directiva:
var buttons = element[0].querySelectorAll(''button'');
for (var i=0; i<buttons.length; i++) {
var target = angular.element(buttons[i]);
console.log(target.attr(''rel'')); // Outputs ''li-0'', ''li-1'', ''li-2'' etc
}
Para la misma solución buscaba la Angularjs directive with ng-Model
.
Aquí está el código que resuelve el problema.
myApp.directive(''zipcodeformatter'', function () {
return {
restrict: ''A'', // only activate on element attribute
require: ''?ngModel'', // get a hold of NgModelController
link: function (scope, element, attrs, ngModel) {
scope.$watch(attrs.ngModel, function (v) {
if (v) {
console.log(''value changed, new value is: '' + v + '' '' + v.length);
if (v.length > 5) {
var newzip = v.replace("-", '''');
var str = newzip.substring(0, 5) + ''-'' + newzip.substring(5, newzip.length);
element.val(str);
} else {
element.val(v);
}
}
});
}
};
});
HTML DOM
<input maxlength="10" zipcodeformatter onkeypress="return isNumberKey(event)" placeholder="Zipcode" type="text" ng-readonly="!checked" name="zipcode" id="postal_code" class="form-control input-sm" ng-model="patient.shippingZipcode" required ng-required="true">
Mi resultado es:
92108-2223
Para un valor de atributo que debe ser interpolado en una directiva que no usa un alcance aislado, por ejemplo,
<input my-directive value="{{1+1}}">
usar el método de atributos $observe
:
myApp.directive(''myDirective'', function () {
return function (scope, element, attr) {
attr.$observe(''value'', function(actual_value) {
element.val("value = "+ actual_value);
})
}
});
Desde la página directive ,
observación de atributos interpolados: use
$observe
para observar los cambios de valor de los atributos que contienen interpolación (por ejemplo,src="{{bar}}"
). Esto no solo es muy eficiente, sino que también es la única forma de obtener fácilmente el valor real, ya que durante la fase de enlace la interpolación no se ha evaluado aún, por lo que el valor en este momento se establece enundefined
.
Si el valor del atributo es solo una constante, por ejemplo,
<input my-directive value="123">
puede usar http://docs.angularjs.org/api/ng.$rootScope.Scope#$eval si el valor es un número o un valor booleano, y desea el tipo correcto:
return function (scope, element, attr) {
var number = scope.$eval(attr.value);
console.log(number, number + 1);
});
Si el valor del atributo es una constante de cadena, o si desea que el valor sea un tipo de cadena en su directiva, puede acceder a él directamente:
return function (scope, element, attr) {
var str = attr.value;
console.log(str, str + " more");
});
Sin embargo, en su caso, dado que desea admitir valores y constantes interpolados, use $observe
.
Aviso: Actualizo esta respuesta a medida que encuentro mejores soluciones. También guardo las respuestas anteriores para futuras referencias siempre que se mantengan relacionadas. La última y mejor respuesta es lo primero.
Mejor respuesta:
Las directivas en angularjs son muy poderosas, pero lleva tiempo comprender qué procesos están detrás de ellas.
Al crear directivas, angularjs le permite crear un ámbito aislado con algunos enlaces al ámbito principal. Estos enlaces están especificados por el atributo que adjunta el elemento en DOM y cómo define la propiedad de ámbito en el objeto de definición de directiva .
Hay 3 tipos de opciones de enlace que puede definir en el alcance y las escribe como atributos relacionados con los prefijos.
angular.module("myApp", []).directive("myDirective", function () {
return {
restrict: "A",
scope: {
text: "@myText",
twoWayBind: "=myTwoWayBind",
oneWayBind: "&myOneWayBind"
}
};
}).controller("myController", function ($scope) {
$scope.foo = {name: "Umur"};
$scope.bar = "qwe";
});
HTML
<div ng-controller="myController">
<div my-directive my-text="hello {{ bar }}" my-two-way-bind="foo" my-one-way-bind="bar">
</div>
</div>
En ese caso, en el ámbito de la directiva (ya sea en la función de enlace o en el controlador), podemos acceder a estas propiedades de la siguiente manera:
/* Directive scope */
in: $scope.text
out: "hello qwe"
// this would automatically update the changes of value in digest
// this is always string as dom attributes values are always strings
in: $scope.twoWayBind
out: {name:"Umur"}
// this would automatically update the changes of value in digest
// changes in this will be reflected in parent scope
// in directive''s scope
in: $scope.twoWayBind.name = "John"
//in parent scope
in: $scope.foo.name
out: "John"
in: $scope.oneWayBind() // notice the function call, this binding is read only
out: "qwe"
// any changes here will not reflect in parent, as this only a getter .
"Todavía está bien" Respuesta:
Ya que esta respuesta fue aceptada, pero tiene algunos problemas, la actualizaré a una mejor. Aparentemente, $parse
es un servicio que no se encuentra en las propiedades del alcance actual, lo que significa que solo toma expresiones angulares y no puede alcanzar el alcance. {{
expresiones {{
, }}
se compilan mientras se inicia angularjs, lo que significa que cuando intentamos acceder a ellas con el método de directivas postlink
, ya están compiladas. ( {{1+1}}
es 2
en la directiva ya).
Así es como querrías usar:
var myApp = angular.module(''myApp'',[]);
myApp.directive(''myDirective'', function ($parse) {
return function (scope, element, attr) {
element.val("value=" + $parse(attr.myDirective)(scope));
};
});
function MyCtrl($scope) {
$scope.aaa = 3432;
}
.
<div ng-controller="MyCtrl">
<input my-directive="123">
<input my-directive="1+1">
<input my-directive="''1+1''">
<input my-directive="aaa">
</div>
Una cosa que debe notar aquí es que, si desea establecer la cadena de valor, debe incluirla entre comillas. (Ver tercera entrada)
Aquí está el violín para jugar: http://jsfiddle.net/neuTA/6/
Respuesta anterior:
No estoy eliminando esto para las personas que pueden ser engañadas como yo, tenga en cuenta que usar $eval
es perfectamente la forma correcta de hacerlo, pero $parse
tiene un comportamiento diferente, probablemente no necesite esto para usarlo en la mayoría de los casos. los casos.
La forma de hacerlo es, una vez más, usando scope.$eval
. No solo compila la expresión angular, sino que también tiene acceso a las propiedades del ámbito actual.
var myApp = angular.module(''myApp'',[]);
myApp.directive(''myDirective'', function () {
return function (scope, element, attr) {
element.val("value = "+ scope.$eval(attr.value));
}
});
function MyCtrl($scope) {
}
Lo que te falta es $eval
.
http://docs.angularjs.org/api/ng.$rootScope.Scope#$eval
Ejecuta la expresión en el alcance actual devolviendo el resultado. Cualquier excepción en la expresión se propaga (no se captura). Esto es útil al evaluar expresiones angulares.
var myApp = angular.module(''myApp'',[]);
myApp .directive(''myDirective'', function ($timeout) {
return function (scope, element, attr) {
$timeout(function(){
element.val("value = "+attr.value);
});
}
});
function MyCtrl($scope) {
}
Use $ timeout porque la directiva llama después de dom cargar para que sus cambios no se apliquen