javascript - Typescript Angularjs Controller Scope udefinert når kalt fra Directive
Jeg er ganske ny på Angularjs og Typescript.
Jeg skal prøve å holde det kort her:
Direktivet (directives/BikeDirective.ts):
class BikeDirective {
constructor() {
var directive: ng.IDirective = {};
directive.restrict = "E";
directive.scope = {
move: "="
};
directive.template = '<div>The bike</div>';
directive.link = (scope, element, attrs: any) => {
element.on('click', (e) => {
scope.move('moving!');
});
}
return directive;
}
}
export = BikeDirective;
Kontrolleren (controllers/MyController):
class MyController {
whatever: string;
constructor(public scope) {
this.whatever = "Whatever";
scope.vm = this;
}
onMove(msg: string) {
console.log(this.whatever);
}
}
export = MyController;
HTML-en:
<div ng-controller="myController">
<my-bike move="vm.onMove"></my-bike>
<my-bike move="vm.onMove"></my-bike>
</div>
app.ts
import MyController = require("controllers/MyController");
import BikeDirective = require("directives/BikeDirective");
class app {
constructor() {
var app = angular.module('app', [])
.controller('myController', ['$scope', MyController])
.directive('myBike', [BikeDirective]);
}
}
export = app;
main.ts
require.config({
baseUrl: '.',
paths: {
jquery: './Scripts/jquery-2.1.0',
angular: './Scripts/angular'
},
shim: {
'angular': {
exports: 'angular'
}
}
});
require(['app','angular','jquery'], (app, angular, $) => {
new app;
angular.bootstrap(document.body, ['app']);
});
Jeg håper koden ovenfor er selvforklarende. I utgangspunktet, hva jeg ønsker å gjøre er at når man klikker på en av syklene (my-bike-direktivet) så kjøres MyController.onMove() funksjonen. Alt dette fungerer fint. Det eneste problemet jeg har er at når onMove kjøres, så gir console.log(this.whatever) undefined, burde det ikke gi strengen "whatever"? Det ser ut som om omfanget til MyController ikke er tilgjengelig i onMove() stuben.
Jeg prøvde dette i vanlig Angularjs (uten TypeScript) og det fungerer fint, går jeg glipp av noe.
Har noen opplevd dette før?
Jeg fulgte .vm-teknikken brukt av Basarat i denne videoen: http://www.youtube.com/watch?v=WdtVn_8K17E
Takk
Svar #1
Problem
Problemet er i move="vm.onMove" du sender en referanse til en funksjon inn i direktivet, det vil si
directive.scope = {
move: "="
};
Å kalle en referanse til en funksjon kobler den fra this.
Rask løsning:
onMove = (msg: string) => {
console.log(this.whatever); //OKAY
}
Dette forklarer this litt mer: https://www.youtube.com/watch?v=tvocUcbCupA&hd=1
Bedre løsning:
Ikke pass funksjoner inn i direktiver, altså ikke bruk = med funksjoner. Bruk i stedet &, altså
directive.scope = {
move: "&"
};
Og deretter kaller du det fra din HTML, dvs. <my-bike move="vm.onMove()"></my-bike>. Å kalle en funksjon med vm., dvs. vm.onMove(), sikrer at this er korrekt inne i funksjonen.
Også ikke relatert til dette problemet
element.on-tilbakekallingen blir ikke kalt i Angular-konteksten ... så du vil kanskje pakke tilbakekallingen inn i en $scope.$apply
