2015-05-10 17 views
9

Mam obiekt data w . Ten obiekt służy do przekazywania danych do dyrektyw first-directive i . W obu przypadkach konieczne jest wiązanie dwóch danych.Przekazywanie paramertów do dyrektyw zagnieżdżonych z izolowanym zakresem

Dla first-directive mijam kompletny obiekt data ale second-directive Chcę przekazać numbers obiekt (scope.numbers = scope.dataFirst.numbers).

Problem:

Kiedy zrobić <div second-directive="dataFirst.numbers"></div>, i sprawdzić, czy dataSecond jest obiektem, zwraca true.

Ale kiedy robię <div second-directive="numbers"></div> i sprawdzam, czy dataSecond jest obiektem, zwraca on false.

W obu przypadkach, jeśli wykonam console.log(scope), zostanie wyświetlona właściwość scope.dataSecond.

Pytanie:

Dlaczego to nie występuje i jaki jest właściwy sposób przekazać params do dyrektyw?

EDIT: Pomysł robi dyrektyw wielokrotnego użytku, a to oznacza, że ​​nie mogą one zależeć od innych dyrektyw.

angular.module('app',[]) 
 

 
.controller('MainCtrl', function($scope) { 
 
    $scope.data = { 
 
    numbers: { 
 
     n1: 'one', 
 
     n2: 'two' 
 
    }, 
 
    letters: { 
 
     a: 'A', 
 
     b: 'B' 
 
    } 
 
    } 
 
}) 
 

 
.directive('firstDirective', function() { 
 
    return { 
 
    template: '<div class="first-directive">\ 
 
     <h2>First Directive</h2>\ 
 
     {{dataFirst}}\ 
 
     <div second-directive="dataFirst.numbers"></div>\ 
 
     <div second-directive="numbers"></div>\ 
 
     </div>', 
 
    replace: true, 
 
    restrict: 'A', 
 
    scope: { 
 
     dataFirst: '=firstDirective' 
 
    }, 
 
    link: function postLink(scope, element, attrs) { 
 
     console.log('first directive') 
 
     console.log(scope) 
 
     scope.numbers = scope.dataFirst.numbers; 
 
    } 
 
    }; 
 
}) 
 

 
.directive('secondDirective', function() { 
 
    return { 
 
    template: '<div class="second-directive">\ 
 
     <h2>Second Directive</h2>\ 
 
     {{dataSecond}}\ 
 
     <div class="is-obj">is an object: {{isObj}}</div>\ 
 
     </div>', 
 
    replace: true, 
 
    restrict: 'A', 
 
    scope: { 
 
     dataSecond: '=secondDirective' 
 
    }, 
 
    link: function postLink(scope, element, attrs) { 
 
     console.log('second directive'); 
 
     console.log(scope) 
 
     
 
     // <div second-directive="XXXX"></div> 
 
     // if 'numbers' returns undefined 
 
     // if 'dataFirst.numbers' returns the object 
 
     console.log(scope.dataSecond); 
 
     
 
     scope.isObj = false; 
 
     
 
     if(angular.isObject(scope.dataSecond)){ 
 
     scope.isObj = true; 
 
     } 
 
    } 
 
    }; 
 
});
h2 { 
 
    padding: 0; 
 
    margin: 0; 
 
} 
 

 
.first-directive { 
 
    background: #98FFDA; 
 
    color: black; 
 
    padding: 10px; 
 
} 
 

 
.second-directive { 
 
    background: #FFA763; 
 
    color: white; 
 
    padding: 10px; 
 
} 
 

 
.is-obj { 
 
    background: blue; 
 
}
<!DOCTYPE html> 
 
<html ng-app="app"> 
 

 
    <head> 
 
    <meta charset="utf-8" /> 
 
    <title>AngularJS Plunker</title> 
 
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script> 
 
    </head> 
 

 
    <body ng-controller="MainCtrl"> 
 
    <h2>MainCtrl</h2> 
 
    {{data}} 
 

 
    <div first-directive="data"> 
 
    </div> 
 

 
    <div second-directive="data"> 
 
    </div> 
 
    </body> 
 

 
</html>

Odpowiedz

10

będę powtarzać tego co inni przede mną powiedział - że funkcja link z firstDirective jest po -link funkcja, która biegnie po funkcja link od secondDirective, i tak scope.numbers nie został jeszcze przypisany obiektowi scope.dataFirst.numbers.

Jednak rozwiązanie, które ściśle wiąże dwie dyrektywy za pośrednictwem require, wydaje mi się nieoptymalne.

Zamiast tego, aby upewnić się, że właściwość jest poprawnie przypisany zakres w dominującej przed dyrektywami/dziecko wewnętrznych run (jak secondDirective, w tym przypadku) jest użycie pre -Link funkcję w firstDirective (zamiast po LINK)

link: { 
    pre: function prelink(scope){ 
     console.log('first directive') 
     console.log(scope) 
     scope.numbers = scope.dataFirst.numbers; 
    } 
} 

Demo

9

Moje rozwiązanie to byłoby mieć drugą dyrektywę dziedziczyć atrybut obiektu danych z pierwszej dyrektywy.

angular.module('app', []) 
 

 
.controller('MainCtrl', function($scope) { 
 
    $scope.data = { 
 
    numbers: { 
 
     n1: 'one', 
 
     n2: 'two' 
 
    }, 
 
    letters: { 
 
     a: 'A', 
 
     b: 'B' 
 
    } 
 
    } 
 
}) 
 

 
.directive('firstDirective', function() { 
 
    return { 
 
    template: '<div class="first-directive">\ 
 
     <h2>First Directive</h2>\ 
 
     {{dataFirst}}\ 
 
     <div second-directive></div>\ 
 
     <div second-directive></div>\ 
 
     </div>', 
 
    replace: true, 
 
    restrict: 'A', 
 
    scope: { 
 
     dataFirst: '=firstDirective' 
 
    }, 
 
    controller: function firstDirectiveController($scope) { 
 
     return $scope; 
 
    }, 
 
    link: function postLink(scope, element, attrs) { 
 
     console.log('first directive') 
 
     console.log(scope) 
 
     scope.numbers = scope.dataFirst.numbers; 
 
    } 
 
    }; 
 
}) 
 

 
.directive('secondDirective', function() { 
 
    return { 
 
    template: '<div class="second-directive">\ 
 
     <h2>Second Directive</h2>\ 
 
     {{dataSecond}}\ 
 
     <div class="is-obj">is an object: {{isObj}}</div>\ 
 
     </div>', 
 
    replace: true, 
 
    require: '^firstDirective', 
 
    link: function postLink(scope, iElement, iAttrs, firstDirectiveController) { 
 
     console.log('second directive'); 
 
     console.log(firstDirectiveController.dataFirst.numbers); 
 
     
 
     scope.dataSecond = firstDirectiveController.dataFirst.numbers; 
 

 
     scope.isObj = false; 
 

 
     if (angular.isObject(scope.dataSecond)) { 
 
     scope.isObj = true; 
 
     } 
 
    } 
 
    }; 
 
}); 
 
h2 { 
 
    padding: 0; 
 
    margin: 0; 
 
} 
 

 
.first-directive { 
 
    background: #98FFDA; 
 
    color: black; 
 
    padding: 10px; 
 
} 
 

 
.second-directive { 
 
    background: #FFA763; 
 
    color: white; 
 
    padding: 10px; 
 
} 
 

 
.is-obj { 
 
    background: blue; 
 
}

 
<!DOCTYPE html> 
 
<html ng-app="app"> 
 

 
    <head> 
 
    <meta charset="utf-8" /> 
 
    <title>AngularJS Plunker</title> 
 
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script> 
 
     <link rel="stylesheet" href="style.css"> 
 
    <script src="script.js"></script> 
 
    </head> 
 

 
    <body ng-controller="MainCtrl"> 
 
    <h2>MainCtrl</h2> 
 
    {{data}} 
 

 
    <div first-directive="data"> 
 
    </div> 
 
    </body> 
 

 
</html>

+2

To dobra odpowiedź, jeśli wiesz zagnieżdżony kolejność dyrektyw w html. Moim pomysłem jest tworzenie komponentów wielokrotnego użytku (takich jak rozwijane), co oznacza, że ​​nie znasz zamówienia. Na przykład, jeśli spróbujesz umieścić "drugą dyrektywę" w '', to nie działa, ponieważ potrzebuje 'pierwszej-dyrektywy'. Dziękuję :) – cespon

+2

To rozwiązanie na pewno działa (chociaż niepotrzebnie ściśle łączy dwie dyrektywy razem), ale dobra odpowiedź powinna być czymś więcej niż tylko kodem. –