AngularJS – izolowany scope i jak mu coś przekazać

Jak wyizolować scope?

Wystarczy niejako nadpisać ten pochodzący od rodzica:

app.directive('myCustomer', function() {
  return {
    scope: {}
  };
});

Dzięki czemu nie dziedziczymy już ze scope rodzica.

Wytrych – czyli jak izolowany scope może dostać coś od rodzica

Aby móc dostać coś od rodzica musi się to zadziać poprzez przesłanie wartości przez atrybut:

<parent-directive>
    <my-cutomer some-attribute="parentScopeVariable"></my-customer>
</parent-directive>

Jak dyrektywa może przyjmować wartość?

@ one-way binding wartości, ale tylko dla wartości tekstowych

Mówi o tym, że wartości przesyłane dla takiego atrybutu będą wartościami tekstowymi (często należy użyć {{expression}}):

app.directive('myCustomer', function() {
  return {
    scope: {
        internalAttributeName: "@someTextAttribute"
    }
  };
});

<parent-directive>
    <my-cutomer some-text-attribute="parentScopeTextVariable"></my-customer>
</parent-directive>

W zmiennej internalAttributeName w obiekcie scope będzie znajdowała się wartość przesłana przez atrybut some-text-attribute i musi ona być typu tekstowego. Warto wspomnieć, że jej zmiany z poziomu dyrektywy nie będą odzwierciedlane w miejscu skąd przyszła (one-way binding).

= two-way binding obiektów

Służy do przesyłania obiektów oraz zapewnia two-way binding. Jeśli coś się zmieni w obiekcie to nasza dyrektywa też otrzyma tą zmianę. I odwrotnie, jeśli nasza dyrektywa coś zmieni w obiekcie to będzie to odzwierciedlone tam skąd przyszedł dany obiekt (na co należy uważać).

app.directive('myCustomer', function() {
  return {
    scope: {
        internalObject: "=someObject"
    }
  };
});

<parent-directive>
    <my-cutomer some-object="parentScopeObjectVariable"></my-customer>
</parent-directive>

W zmiennej internalObject w obiekcie scope będzie znajdował się obiekt przesłany przez atrybut some-object. I podlegać on będzie pod two-way binding pomiędzy tym obiektem scope a obiektem scope od którego przychodzi.

& one-way binding funkcji

Służy do przesyłania funkcji do dyrektywy, tak aby ta została wywołana w odpowiednim momencie/miejscu. Daje to możliwość otrzymywania niejako wartości z dyrektywy dziecka w dyrektywie rodzicu.

app.directive('myCustomer', function() {
  return {
    scope: {
        internalFunction: "&someFunction",
        doSomethingSpecial: function(){
            internalFunction();
        }
    }
  };
});

<parent-directive>
    <my-cutomer some-function="parentFunction"></my-customer>
</parent-directive>

Możliwe jest także przesyłanie argumentów:

app.directive('myCustomer', function() {
  return {
    scope: {
        internalFunction: "&someFunction",
        doSomethingSpecial: function(){
            internalFunction({changes: 'some changes'});
        }
    }
  };
});

app.directive('parentDirective', function() {
  return {
    scope: {
        alertAboutChanges: function(changes){
            alert(changes);
        }
    }
  };
});

<parent-directive>
    <my-cutomer some-function="alertAboutChanges(changes)"></my-customer>
</parent-directive>

Jak widać składnia nie zachęca 🙂 najważniejsze o czym trzeba pamiętać to ta sama nazwa argumentów (zarówno w dyrektywie rodzica jak i dziecka) oraz przesyłanie argumentów przez stworzenie obiektu ( {changes: 'some changes’} ).

< one-way binding obiektów

Służy do obsługi one-way bindingu dla obiektów (wprowadzone jednak dopiero w wersji 1.5 AnuglarJS). Obiekt w tym wypadku jest przesyłany do dyrektywy, ale jego zmiany w tej dyrektywie nie są propagowane do miejsca skąd pochodzi dany obiekt. Ogólnie zaleca się użycie tego symbolu zamiast @.

app.directive('myCustomer', function() {
  return {
    scope: {
        internalObject: "<someObject"
    }
  };
});

<parent-directive>
    <my-cutomer some-object="parentScopeObjectVariable"></my-customer>
</parent-directive>