2016-02-05 7 views
9

Mam linię poleceń z widokiem drzewa do http://codepen.io/bachly/pen/KwWrzG za bycie moim początkowym blokiem. który próbuję zaktualizować po dodaniu obiektów do kolekcji. Mogę zaktualizować obiekt i wstawić nowe obiekty, ale dyrektywa widoku drzewa nigdy nie jest wywoływana po zaktualizowaniu elementu $scoped. Ostatecznie użyte dane będą pochodzić z usługi w tym momencie właśnie testuję z próbnymi danymi.Zaktualizuj dyrektywę kątowego widoku drzewa, gdy nowy obiekt zostanie dodany do kolekcji

Oryginalna kolekcja wygląda następująco

$scope.myList = { 
      children: [ 
       { 
        name: "Event", 
        children: [ 
        { 
         name: "Event Date", 
         parent:"Event", 
         children: [ 
          { 
           name: "2008", 
           filterType: '_eventStartDate', 
           parent: 'Event' 
          }, 
          { 
           name: "2009", 
           filterType: '_eventStartDate', 
           parent: 'Event' 
          } 
         ] 
        }, 
        { 
         name: "Event Attendee", 
         parent: "Event", 
         children: [ 
          { 
           name: "Person 1", 
           filterType: '_eventAttenddeeName', 
           parent: 'Event Attendee' 
          }, 
          { 
           name: "Person 2", 
           filterType: '_eventAttenddeeName', 
           parent: 'Event Attendee' 
          } 
         ] 
        } 
        ] 
       }] 
    }; 


    var TheOtherCollection = { 
     children: [ 
     { 
      name: "A New Event", 
      children: [ 
       { 
        name: "The Other Date", 
        parent: " A New Event", 
        children: [ 
        { 
         name: "2010", 
         FilterType: '_eventStartDate', 
         Parent: '_event' 
        }, 
        { 
         name: "2011", 
         FilterType: '_eventStartDate', 
         Parent: '_event' 
        } 
        ] 
       } 
      ] 
     }] 
    }; 

Generuje widok drzewa z pola wyboru stosując następującą dyrektywę i HTML

app.directive('tree', function() { 
    return { 
     restrict: 'E', 
     replace: true, 
     scope: { 
      t: '=src', 
      filter: '&' 
     }, 
     controller: 'treeController', 
     template: '<ul><branch ng-repeat="c in t.children track by $index" src="c" filter="doSomething(object, isSelected)"></branch></ul>' 
    }; 
}); 

app.directive('branch', function($compile) { 

    return { 
     restrict: 'E', 
     replace: true, 
     scope: { 
      b: '=src', 
      filter: '&', 
      checked: '=ngModel' 
     }, 

      template: '<li><input type="checkbox" ng-click="innerCall()" ng-model="b.$$hashKey" ng-change="stateChanged(b.$$hashKey)" ng-hide="visible" /><a>{{ b.name }}</a></li>', 
      link: function (scope, element, attrs) { 

       var clicked = ''; 
       var hasChildren = angular.isArray(scope.b.children); 
       scope.visible = hasChildren; 
       if (hasChildren) { 
        element.append('<tree src="b"></tree>'); 
        $compile(element.contents())(scope); 
       } 
       element.on('click', function(event) { 
        event.stopPropagation(); 
        if (hasChildren) { 
         element.toggleClass('collapsed'); 
        } 
       }); 
       scope.stateChanged = function(b) { 
        clicked = b; 
       }; 

       scope.innerCall = function() { 
        scope.filter({ object: scope.b, isSelected: clicked }); 
       }; 
      } 
     }; 
    }); 

a następnie html

<div ng-controller="treeController"> 
     <tree src="myList" iobj="object" filter="doSomething(object, isSelected)"></tree> 

     <a ng-click="clicked()"> link</a> 
    </div> 

Kiedy zaznaczone jest pole wyboru, nowa kolekcja jest dodawana do istniejącej za pomocą loda shjs

ng kliknięciem wydarzenie

$scope.doSomething = function (object, isSelected) { 
    if (isSelected) { 
     var item = object; 
     console.log(item); 
     nestAssociation(object, $scope.myList, TheOtherCollection); 
    } 
} 

który tworzy nową tablicę i dodaje ją w tablicy dzieci

function nestAssociation(node, oldCollection, newAggregates) { 
    // var item = fn(oldCollection, node.parent); 
    var updatedArray = _.concat(oldCollection.children, newAggregates); 
    console.log(updatedArray); 
    if (updatedArray != null) 
     updateMyList(updatedArray); 
} 

widzę na wyjściu mam nowy obiekt, ale mogę” t uzyskać widok drzewa do aktualizacji. Próbowałem w dyrektywie, aby dodać $ compile (element) na zdarzenie click w dyrektywie, ale ponieważ tablica nie została jeszcze zbudowana, nic się nie zmienia.

Czy muszę dodać zegarek $ do tej dyrektywy, a jeśli tak, to gdzie jest inny sposób, mogę spowodować, że dyrektywa ponownie wyrenderuje i wyświetli nową zagnieżdżoną kolekcję?

Aktualizacja

bazowa na niektóre z opinii i pytań o to trochę bardziej szczegółowo wokół pytania. Problem, który widzę nie znajduje się w dyrektywie, jeśli chodzi o przenoszenie danych wokół problemu, nie mogę uzyskać ponownego wyświetlenia drzewa po dodaniu tablicy do istniejącego modelu. Poniższy link is a working plunker pokazuje projekt w aktualnym stanie. przebiegu narzędzia chrom dev widzę w wyjściowym modelu jest aktualizowana po pole wyboru jest zaznaczone enter image description here

Choć widzę obiekt jest aktualizowany, nigdy dyrektywa aktualizuje pokazać nowa tablica dodana do obiektu. To jest ta część, której potrzebuję, aby pomóc w zrozumieniu.

góry dzięki

+1

Byłoby świetnie, gdybyś mógł stworzyć plunkr lub codepen, gdzie moglibyśmy zobaczyć rzeczywisty problem i pracować w twoim kodzie (jak rozumiem, połączony codepen był tylko twoim punktem wyjścia). –

+0

Czy możesz opublikować kod funkcji 'updateMyList', która jest wywoływana przez' nestAssociation() '. Domyślam się, że to jest miejsce, w którym faktycznie zapisujesz zaktualizowany Array w '$ scope.myList' –

+1

Mam zaktualizowane moje pytanie z linkiem plunker – rlcrews

Odpowiedz

4

przekazać funkcję do wewnętrznych dyrektyw (co jest najlepsze praktyki), ale masz dostęp do scope.filter. Nie doSomethingFunction. Ten jest tam undefined.

filter="doSomething(object, isSelected)"
=>
filter="filter(object, isSelected)"

app.directive('tree', function() { 
    return { 
     restrict: 'E', 
     replace: true, 
     scope: { 
      t: '=src', 
      filter: '&' 
     }, 
     controller: 'treeController', 
     template: '<ul> 
        <branch ng-repeat="c in t.children track by $index"  
        src="c" filter="filter(object, isSelected)"> 
        </branch> 
        </ul>' 
    }; 
}); 

Następny:

Nigdy nie można uzyskać dostęp $$ zmienne w angularjs, bo są prywatne. Może powinieneś zrobić jeden z DB ..., ale $$hashkey wydaje się jednak łatwym rozwiązaniem.

checked atrybut może spowodować błąd, ponieważ ngModel nie istnieje w szablonie dyrektywy drzewa. (wstaw co najmniej ?)

Pole wyboru nie może mieć modelu $$ hashkey.
Ng-change i ng-click będą zawsze wywoływane w tym samym czasie, użyj najprostszego.

app.directive('branch', function($compile) { 

    return { 
     restrict: 'E', 
     replace: true, 
     scope: { 
      b: '=src', 
      filter: '&' 
     }, 

      template: '<li><input type="checkbox" ng-click="innerCall(b.$$hashKey)" ng-model="isChecked" ng-hide="visible" /><a>{{ b.name }}</a></li>', 
      link: function (scope, element, attrs) { 

       scope.isChecked = false; 
       var hasChildren = angular.isArray(scope.b.children); 
       scope.visible = hasChildren; 
       if (hasChildren) { 
        element.append('<tree src="b"></tree>'); 
        $compile(element.contents())(scope); 
       } 
       element.on('click', function(event) { 
        event.stopPropagation(); 
        if (hasChildren) { 
         element.toggleClass('collapsed'); 
        } 
       }); 

       scope.innerCall = function(hash) { 
        if(scope.isChecked){ 
         scope.filter({ object: scope.b, isSelected: hash }); 
        } 

       }; 
      } 
     }; 
    }); 

UPDATE

masz ten sam treeController w swoim dyrektywy tree i w widoku index.html. To powoduje, że widok nie aktualizuje się!

Usunąłem ten w twojej dyrektywie, w przeciwnym razie będziesz miał kontroler dla każdego dziecka.
Widziałeś dobrą wiadomość console.log w kontrolerze, ale był on w kontrolerze dla JEDNEJ dyrektywy.
Nie uzyskiwałeś dostępu do kontrolera urządzenia index.html.

Potem stałą komunikację filter funkcyjny między Childs:

zapomniałeś komunikować funkcję filtra podczas dołączania nowych tree Add

element.append('<tree src="b" filter="filter({ object: object, isSelected: isSelected })"></tree>');

Również w swoim dyrektywy szablonu nadrzędnego, potrzebujesz również skrótu do wysłania parametrów do funkcji:
filter="filter({ object: object, isSelected: isSelected })"

Zmieniłem twój Plunker HERE bez zmiany kodu z powyższymi komentarzami, które zrobiłem.
(Nie jestem pewien, co piszesz, nie jest to, co chcesz, a ponieważ nie komentowałeś, raczej go nie zmienię, abyś szybko podał swój kod)
Ale widok jest teraz aktualizowany!
Myślę, że trochę debugowania, co chcesz, a powyższe komentarze powinny wystarczyć.

EDIT 2
zapomniałeś zwrócić obiekt z właściwością chrilden. Zwróciłeś tablicę, która spowodowała problem.

function updateMyList(data) { 
     var transformed = { children : data }; 
     $scope.myList = transformed; 
    } 

Oto działa PLUNKER.

0

Spróbuj $. $ Zakres zastosowania() po dodaniu

+0

Próbowałem wcześnie $ scope. $ Apply() lub $ scope. $ Apply (function() {...}) nie zadziała, ponieważ funkcja jest aktualnie w cyklu $ apply(). Tak więc nie może wywołać nowego. – rlcrews

+1

@ricrews Możesz uniknąć problemu z błędem $ apply, zawijając swoje wezwanie do $ scope. $ Apply in $ timeout call – twsaef

Powiązane problemy