AngularJS'de iki yönlü filtreleme nasıl yapılır?


124

AngularJS'nin yapabileceği ilginç şeylerden biri, belirli bir veri bağlama ifadesine filtre uygulamaktır; bu, örneğin kültüre özgü para birimi veya bir modelin özelliklerinin tarih biçimlendirmesini uygulamanın uygun bir yoludur. Kapsamda hesaplanmış özelliklerin olması da güzel. Sorun, bu özelliklerin hiçbirinin iki yönlü veri bağlama senaryoları ile çalışmamasıdır - kapsamdan görünüme yalnızca tek yönlü veri bağlama. Bu, başka türlü mükemmel bir kütüphanede göze batan bir ihmal gibi görünüyor - yoksa bir şeyi mi kaçırıyorum?

Gelen KnockoutJS , bana fonksiyonların bir çift, mülkün değeri elde etmek denir birini ve özellik ayarlandığında denir birini belirtmek için izin verilen bir okuma / yazma bilgisayarlı özelliğini oluşturabilir. Bu, örneğin, kültüre duyarlı girdiyi uygulamama - kullanıcının "$ 1.24" yazmasına ve bunu ViewModel'de bir kayan nokta olarak ayrıştırmasına ve ViewModel'deki değişikliklerin girdiye yansıtılmasına izin verdi.

Buna benzer bulabildiğim en yakın şey şudur: $scope.$watch(propertyName, functionOrNGExpression);Bu, bir özellik $scopedeğiştiğinde bir işlevi çalıştırmama izin verir . Ancak bu, örneğin kültüre duyarlı girdi sorununu çözmez. $watchedÖzelliği $watchyöntemin kendisinde değiştirmeye çalıştığımda sorunlara dikkat edin :

$scope.$watch("property", function (newValue, oldValue) {
    $scope.outputMessage = "oldValue: " + oldValue + " newValue: " + newValue;
    $scope.property = Globalize.parseFloat(newValue);
});

( http://jsfiddle.net/gyZH8/2/ )

Giriş öğesi, kullanıcı yazmaya başladığında çok karışır. Özelliği, biri ayrıştırılmamış değer ve biri ayrıştırılmış değer için olmak üzere iki özelliğe bölerek geliştirdim:

$scope.visibleProperty= 0.0;
$scope.hiddenProperty = 0.0;
$scope.$watch("visibleProperty", function (newValue, oldValue) {
    $scope.outputMessage = "oldValue: " + oldValue + " newValue: " + newValue;
    $scope.hiddenProperty = Globalize.parseFloat(newValue);
});

( http://jsfiddle.net/XkPNv/1/ )

Bu, ilk sürüme göre bir gelişmedir, ancak biraz daha ayrıntılıdır ve parsedValuekapsam değişikliklerinin özelliğinde hala bir sorun olduğuna dikkat edin (ikinci girdiye parsedValuedoğrudan değiştiren bir şey yazın . Üst girdinin Güncelleme). Bu, bir denetleyici eyleminden veya bir veri hizmetinden veri yüklemeden kaynaklanabilir.

AngularJS kullanarak bu senaryoyu uygulamanın daha kolay bir yolu var mı? Belgelerde bazı işlevler eksik mi?

Yanıtlar:


231

Görünüşe göre bunun için çok zarif bir çözüm var, ancak bu iyi belgelenmemiş.

Ekran için biçimlendirme model değerleri |operatör tarafından ve bir açısal olarak ele alınabilir formatter. Sadece biçimlendiricilerin bir listesine değil, aynı zamanda bir ayrıştırıcı listesine sahip olan ngModel'in olduğu ortaya çıktı.

1. ng-modelİki yönlü veri bağlamayı oluşturmak için kullanın

<input type="text" ng-model="foo.bar"></input>

2. Açısal modülünüzde aynı öğeye uygulanacak ve ngModeldenetleyiciye bağlı bir yönerge oluşturun

module.directive('lowercase', function() {
    return {
        restrict: 'A',
        require: 'ngModel',
        link: function(scope, element, attr, ngModel) {
            ...
        }
    };
});

3. linkYöntem içinde, özel dönüştürücülerinizi ngModeldenetleyiciye ekleyin

function fromUser(text) {
    return (text || '').toUpperCase();
}

function toUser(text) {
    return (text || '').toLowerCase();
}
ngModel.$parsers.push(fromUser);
ngModel.$formatters.push(toUser);

4. Yeni direktifinizi, halihazırda ngModel

<input type="text" lowercase ng-model="foo.bar"></input>

İşte modelde metni küçük harfe ve tekrar büyük harfe dönüştüren bir çalışma örneğiinput

Model Kontrolörü için API Belgeleri de kısa bir açıklama ve mevcut diğer yöntemlerin genel bir bakış vardır.


Bağlama işlevinizde dördüncü parametrenin adı olarak "ngModel" kullanmanızın herhangi bir nedeni var mı? Bu, temelde ngModel özniteliğiyle hiçbir ilgisi olmayan yönerge için genel bir denetleyici değil mi? (Hala burada açısal öğreniyorum, bu yüzden tamamen yanılıyor olabilirim.)
Drew Miller

7
"Required: 'ngModel" "nedeniyle, bağlantı fonksiyonunun 4. parametresi ngModel direktifinin denetleyicisi olacaktır - yani, ngModelController'ın bir örneği olan foo.bar'ın denetleyicisi . 4. parametreyi istediğiniz gibi adlandırabilirsiniz. (Adını ngModelCtrl
verirdim

8
Bu teknik, docs.angularjs.org/guide/forms adresinde Özel Doğrulama bölümünde belgelenmiştir .
Nikhil Dabas

1
@Mark Rajcok sağlanan keman içinde, Verileri Yükle'yi tıklarken - tümü küçük harf, model değerinin TÜM BÜYÜK HARF içinde olmasını bekliyordum, ancak model değeri küçüktü. Lütfen lütfen. nasıl CAPS hep modelini yapmak için neden ve açıklamak
Rajkamal SUBRAMANIAN

1
@rajkamal, loadData2 () $scopedoğrudan değiştirildiği için, kullanıcı metin kutusuyla etkileşime girene kadar modelin ... Bu noktada, herhangi bir ayrıştırıcı model değerini etkileyebilir. Ayrıştırıcıya ek olarak, model değerini dönüştürmek için denetleyicinize bir $ watch ekleyebilirsiniz.
Mark Rajcok
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.