javascript - Özel bir yönerge içinde değerlendirilen öznitelikler nasıl alınır
Özel yönergemden değerlendirilmiş bir öznitelik almaya çalışıyorum, ama bunu yapmanın doğru yolunu bulamıyorum.
Bunu açıklamak için bu jsFiddle'ı oluşturdum.
<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);
}
});
Eksik olan ne?
Cevap #1
Not: Daha iyi çözümler buldukça bu cevabı güncelliyorum. Ayrıca, eski cevapları ilgili oldukları sürece gelecekteki referans için saklıyorum. En son ve en iyi cevap en başta yer alır.
Daha iyi cevap:
AngularJS'teki yönergeler çok güçlüdür, ancak arkasında hangi süreçlerin yattığını anlamak zaman alır.
Directive oluştururken, AngularJS size bazı üst seviye scope bağlamalarıyla bir izole scope oluşturma imkanı tanır. Bu bağlamalar, DOM'da elementi eklediğiniz attribute ile ve directive tanım nesnesinde scope özelliğini nasıl tanımladığınıza göre belirtilir.
Kapsamda tanımlayabileceğiniz 3 tür bağlama seçeneği vardır ve bunları ilgili özniteliklerin ön ekleri olarak yazarsınız.
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>
Bu durumda, bu direktifin kapsamı içinde (ister bağlama fonksiyonunda ister denetleyicide), bu özelliklere şu şekilde erişebiliriz:
/* 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 .
"Hâlâ Tamam" Cevap:
Bu cevap kabul edildiği için ama bazı sorunlar içerdiği için, bunu daha iyi bir şekilde güncelleyeceğim. Görünüşe göre, $parse mevcut kapsamın özellikleri arasında yer almayan bir servistir, bu da yalnızca Angular ifadelerini alabileceği ve scope'a erişemeyeceği anlamına gelir. {{,}} ifadeleri AngularJS başlatılırken derlenir, bu da bizim bunlara direktiflerimizin postlink metodunda erişmeye çalıştığımızda, onların zaten derlenmiş olduğu anlamına gelir. ({{1+1}} direktif içinde zaten 2 olur).
Bunu şöyle kullanmak istersiniz:
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>
Burada dikkat etmeniz gereken bir şey, eğer değer dizisini ayarlamak istiyorsanız, onu tırnak içine almanız gerektiğidir. (3. girişi görün)
Denemek için işte fiddle: http://jsfiddle.net/neuTA/6/
Eski Cevap:
Ben bunu benim gibi yanlış yönlendirilebilecek kişiler için kaldırmıyorum, $eval kullanmanın doğru yoluyla tamamen uygun olduğunu unutmayın, ancak $parse farklı bir davranış sergiler, çoğu durumda bunu kullanmanız muhtemelen gerekmeyecektir.
Bunu yapmanın yolu, bir kez daha, scope.$eval kullanmaktır. Sadece Angular ifadesini derlemekle kalmaz, aynı zamanda mevcut scope'un özelliklerine de erişebilir.
var myApp = angular.module('myApp',[]);
myApp.directive('myDirective', function () {
return function (scope, element, attr) {
element.val("value = "+ scope.$eval(attr.value));
}
});
function MyCtrl($scope) {
}
Kaçırdığınız şey $eval idi.
http://docs.angularjs.org/api/ng.$rootScope.Scope#$eval
İfadeyi mevcut kapsamda çalıştırır ve sonucu döndürür. İfadedeki tüm istisnalar yayılır (yakalanmaz). Bu, Angular ifadelerini değerlendirirken faydalıdır.
Cevap #2
İzole bir alan kullanmayan bir yönergede, örneğin, ara değerlemesi gereken bir öznitelik değeri için,
<input my-directive value="{{1+1}}">
Attributes yöntemini kullan $observe:
myApp.directive('myDirective', function () {
return function (scope, element, attr) {
attr.$observe('value', function(actual_value) {
element.val("value = "+ actual_value);
})
}
});
Yönerge sayfasından,
Ara katman değerlerini izleme: Ara katman içeren özniteliklerin değer değişikliklerini izlemek için
$observekullanın (ör.src="{{bar}}"). Bu yalnızca çok verimli olmakla kalmaz, aynı zamanda gerçek değeri kolayca elde etmenin tek yoludur çünkü bağlama (linking) aşamasında ara katman henüz değerlendirilmemiştir ve bu nedenle değer bu aşamadaundefinedolarak ayarlanmıştır.
Eğer öznitelik değeri sadece sabit bir değer ise, örneğin,
<input my-directive value="123">
Değer bir sayı veya boolean ise ve doğru türü istiyorsanız $eval kullanabilirsiniz:
return function (scope, element, attr) {
var number = scope.$eval(attr.value);
console.log(number, number + 1);
});
Eğer öznitelik değeri bir dize sabiti ise veya değerinin yönergenizde dize türünde olmasını istiyorsanız, ona doğrudan erişebilirsiniz:
return function (scope, element, attr) {
var str = attr.value;
console.log(str, str + " more");
});
Ancak sizin durumunuzda, ara değerleri ve sabitleri desteklemek istediğiniz için $observe kullanın.
