1

Ziel ist es, zwei verschiedene Direktiven, die technisch Geschwister-Share-Funktionalität haben. Ich werde entweder eine oder die andere, nie eine innerhalb der anderen verwenden.Angular Controller Vererbung Scoping-Probleme

Die zweite Direktive wird jedoch die ganze Leistungsfähigkeit des ersten mit einigen kleinen Zusätzen haben. Aus diesem Grund möchte ich die Funktionalität erben von der "Parent" -Direktive auf die "Child".

Ich erreiche dies, indem ich das selbe Direktiven-Definitionsobjekt vom Parent auf dem Child wiederverwende, mit Ausnahme der Controller-/Template-Felder, die geändert werden.

Das war alles gut funktioniert, bis ich die Beobachter von meinem ParentDirCtrl traf. Aus irgendeinem Grund scheint der Watcher korrekt eingestellt zu sein und beobachtet mydir.obj1 und irgendwie wird die Callback-Funktion mydir.obj1 des Watchers irgendwie undefiniert.

Ich gehe davon aus, etwas über _.extend/$controller verändert, wie die $scope Arbeit so mydir.obj1 nicht in den ParentDirCtrl definiert ist, aber ich bin nicht sicher, warum das der Fall wäre.

Plunk

angular.module('plunker', []) 

// lodash 
.constant('_', _) 

.controller('MainCtrl', function($scope, $timeout) { 
    $scope.obj = { 
    name: 'John', 
    age: 30, 
    }; 
}) 


.controller('ParentDirCtrl', function($scope) { 
    var mydir = this; 

    mydir.doStuffInParent = function() { 
    alert('executed from the parent directive'); 
    } 

    $scope.$watch('mydir.obj1', function() { 
    // ==================================== 
    //    ERROR 
    // Why is 'mydir.obj1' undefined when 
    // occupation is set? 
    // ==================================== 
    mydir.obj1.occupation = 'Meteorologist'; 
    }); 
}) 


.directive('parentDirective', parentDirective) 


.directive('childDirective', function() { 
    // borrow the directive definition object from the parent directive 
    var parentDDO = parentDirective(); 

    // uodate the template and controller for our new directive 
    parentDDO.template = [ 
    '<div>', 
     '<p ng-click="mydir.doStuffInParent()">{{mydir.obj1.name}}</p>', 
     '<p ng-click="mydir.doStuffInChild()">{{mydir.obj1.age}}</p>', 
    '</div>' 
    ].join(''); 

    parentDDO.controller = function($scope, $controller, _) { 
     // extend 'this' with the Parent's controller 
     var mydir = _.extend(this, $controller('ParentDirCtrl', { $scope: $scope })); 

     mydir.doStuffInChild = function() { 
     alert("executed from the child directive"); 
     }; 
    }; 

    return parentDDO; 
}); 


// this will be moved to the top during declaration hoisting 
function parentDirective() { 
    return { 
    restrict:'E', 
    scope: {}, 
    bindToController: { 
     obj1: '=', 
    }, 
    template: '<div>{{mydir.obj1}}</div>', 
    controller: 'ParentDirCtrl', 
    controllerAs: 'mydir', 
    }; 
} 
+0

Wenn sie im Wesentlichen die gleichen sind, warum können Sie nicht alle Funktionen in einem unterscheiden, indem Sie ein Attribut setzen? – charlietfl

+0

Das Kind wird einige Funktionen haben, die die Eltern überschreiben und dann eine Reihe von Funktionen, die im Elternteil einfach nicht benötigt werden. Zusätzlich wird es einige Beobachter für Attribute geben, die nicht auf dem Elternteil existieren. Das heißt, 100% der Funktionalität in der Eltern wird im Kind benötigt. Es würde eine Menge Bedingungen erfordern, um all dies in einer einzigen Richtlinie zu kontrollieren. – diplosaurus

+0

'var mydir' ist' this' erweitert um die Eigenschaften des übergeordneten Controllers. Mein Verständnis ist, dass dies die Art ist, von einem anderen Controller zu erben. – diplosaurus

Antwort

1

obj1 ist auf dem Kind Controller-Instanz bevölkert - deshalb mydir.obj1 in der Mutter Beobachter nicht definiert ist. Sie können obj1 direkt über Umfang zugreifen oder durch den Verweis in den Beobachter bestanden mit:

$scope.$watch('mydir.obj1', function(val) { 
    $scope.mydir.obj1.occupation = 'Meteorologist'; 
    // or 
    val.occupation = 'Meteorologis'; 
}); 

Es gibt keine Umfang Vererbung hier ist - beide Controller auf dem gleichen Umfang arbeiten. Controller-AS Syntax ist, was Sie verwirrt - ich würde es loswerden, um die Dinge klarer zu machen.

+0

Danke, ich nahm Ihren Rat und aktualisiert, um Controller-As-Syntax Graben. Der Fehler ist weg, aber der Watcher schießt überhaupt nicht mehr: https://plnkr.co/edit/oVCoPW?p=preview Es scheint, dass dieser Watcher nach dem '$ timeout' feuern sollte. – diplosaurus

+1

Um die von 'angular.copy' gemachten Änderungen abzufangen, setzen Sie den dritten Parameter (' objectEquality') der '$ watch' Methode auf' true'. 'angular.copy' ändert die Referenz des Ziels nicht. –

+0

ah, duh. Sollte $ watchCollection verwendet haben. Vielen Dank! – diplosaurus

Verwandte Themen