angularjs - Angular-direktiv, der modtager objekt som attribut ved brug af Typescript
Jeg udvikler med Angular 1.5.8 og Typescript. Jeg har en direktiv, som bruges under scope af en anden direktiv (og selvfølgelig en anden controller). Lad os sige Directive1, Controller1 og Directive2, Controller2. Givet at Controller1 allerede har brugerinformationen, vil jeg gerne videregive denne brugerinformation til Controller2 gennem Directive2 for at undgå at indhente informationen igen fra backend. Jeg er ikke sikker på, om dette kan lade sig gøre, men det ville være rart, hvis det er tilfældet :)
Nedenfor er koden til at hjælpe min forklaring:
Direktiv1 HTML:
<div>
...
<directive2 user="{{ctrl.loggedUser}}"></directive2>
...
</div>
loggedUser indlæses i Controller1-konstruktøren gennem et kald til backenden.
Directive2 og Directive2Ctrl Typescript-kode:
class Directive2 implements ng.IDirective {
controller = "Directive2Ctrl";
controllerAs = "d2Ctrl";
bindToController = {
user: "@"
};
restrict = "E";
templateUrl = "directive2.html";
static factory(): ng.IDirectiveFactory {
const directive = () => new Directive2();
return directive;
}
}
angular
.module("app")
.controller("Directive2Ctrl", Directive2Ctrl)
.directive("directive2", Directive2.factory());
class Directive2Ctrl implements IDirective2Ctrl {
public user: User;
constructor(user: User) {
// user is undefined
}
$onInit(user: User): void {
// user is undefined
}
}
Jeg kunne ikke finde en måde at videregive brugerobjektet til Directive2Ctrl (er ikke engang sikker på, om det er muligt).
Svar #1
Brug "scope"-egenskaben i stedet for "bindToController"-egenskaben, og erstat din "@" med "=". Derefter bruger jeg et interface for mit specifikke scope for at få autoudfyldelse.
export interface IMyDirectiveScope extends ng.IScope {
user: any;
}
export class Myirective {
public restrict: string = 'E';
public templateUrl = "/mytemplate.html";
public link: (scope: IMyDirectiveScope, element: ng.IAugmentedJQuery, attrs: ng.IAttributes, ngModel: ng.INgModelController) => void;
public scope = {
user: "="
};
constructor() {
var context = this;
context.link = (scope: IMyDirectiveScope, element: ng.IAugmentedJQuery, attrs: ng.IAttributes, ngModel: ng.INgModelController) => {
//INSERT YOUR CODE
//console.log(scope.user);
};
}
public static Factory() {
var directive = () => {
return new MyDirective();
};
return directive;
}
}
I dit html, fjern dine krøllede parenteser.
<div>
...
<directive2 user="ctrl.loggedUser"></directive2>
...
</div>
Svar #2
Hvis du vil dele data mellem forskellige steder i din applikation, skal du bare lægge det i en service og bruge DI, hvor du har brug for dataene.
Det vil sige, hent dataene, gem dem i en service og brug DI for at gøre dataene tilgængelige forskellige steder. Der er ikke behov for at videregive data gennem bindings over flere lag, meget nemmere at bruge en service.
var mod = angular.module('testApp', ['ngRoute']);
mod.config(['$routeProvider',
function($routeProvider) {
$routeProvider.
when('/intern', {
template: '<div class="outer" ng-controller="InternController">{{User.firstName}} <div class="nested" ng-controller="NestedController">{{NestedUser.lastName}}<test-dir></test-dir></div></div>',
resolve: {
userResolve: function($q, $timeout, User) {
var deferred = $q.defer();
// mock server call, which returns server data
$timeout(function() {
var mockUserResp = {
firstName: 'John',
lastName: 'Rambo'
};
User.setUser(mockUserResp);
deferred.resolve();
}, 1000);
return deferred.promise;
}
}
}).
otherwise({
redirectTo: '/intern'
});
}]);
mod.factory('User', function() {
var _user = null;
return {
setUser: function(user) {
_user = user;
},
getUser: function() {
return _user;
}
}
});
mod.controller('InternController', function($scope, User) {
$scope.User = User.getUser();
});
mod.controller('NestedController', function($scope, User) {
$scope.NestedUser = User.getUser();
});
mod.directive('testDir', function(User) {
return {
restrict: 'EA',
scope: {},
template: '<div class="dir">{{firstName}} is a cool guy.</div>',
link: function(scope) {
scope.firstName = User.getUser().firstName;
}
};
});.outer {
border: 1px solid green;
}
.nested {
border: 1px solid blue;
}
.dir {
border: 1px solid orange;
}<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.12/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.12/angular-route.min.js"></script>
<div ng-app="testApp">
<div ng-view></div>
</div>