Same issue as here: AngularJS directive binding a function with multiple arguments
Following this answer: https://stackoverflow.com/a/26244600/2892106
In as small of a nutshell as I can.
This works:
<my-directive on-save="ctrl.saveFn"></my-directive>
With:
angular.module('app')
.controller('MyController', function($scope) {
var vm = this;
vm.saveFn = function(value) { vm.doSomethingWithValue(value); }
});
But when I convert to Typescript and use real classes, this breaks.
class MyController {
constructor() {}
saveFn(value) {
this.doSomethingWithValue(value);
}
}
In the Typescript version when debugging, "this" is referencing the Window global. So my scope is messed up somehow, but I don't know how to fix it. How can I get "this" to refer to MyController as expected?
So my scope is messed up somehow
Use an arrow function instead of a method.
Fixed
class MyController {
constructor() {}
saveFn = (value) => {
this.doSomethingWithValue(value);
}
}
More
https://basarat.gitbooks.io/typescript/content/docs/arrow-functions.html
Related
Hi I am using Angular with ES6, now I want to get rid of the $scope since Angular2 will not use it anymore and I want to create futureprove code,... this works:
let tab = this.tabManager.getArea.open({
controller: ['$scope', function (scope) {
console.log(scope);
scope.close = function () {
tab.close();
}
}],
template: '<component-name on-close="close()" ...></component-name>'
});
but how do I rewrite it without injecting the scope, I thought about something like this:
let tab = this.tabManager.getArea.open({
controller: [class {
constructor() {
console.log('construct');
}
close() {
console.log('close');
tab.close();
}
}],
template: '<component-name on-close="close()" ...></component-name>'
});
But it does not seem to work properly, the construtor is called up, however the binding for on-close does not seem to work.
the controller class in 1.6 exposes $ctrl object , can access "close()" using that.try once
How come I don't have scope for $scope outside of the constructor, unless I define my function using the fat arrow? Or is it possible to access $scope without defining a function using fat arrow?
namespace FooBar {
export interface MyScope extends ng.IScope {
message: string;
}
export class SandboxCtrl {
static $inject = ["$scope", "$timeout"];
private scope: MyScope;
private timeout: ITimeoutService;
constructor($scope: MyScope, $timeout: ng.ITimeoutService) {
this.scope = $scope;
this.timeout = $timeout;
timeout(this.foo, 1000); // does not work
timeout(this.bar, 1000); // works
}
public foo() {
this.scope.message = "foo bar"; // does not work
}
bar = () => {
this.scope.message = "foo bar"; // works
}
}
}
UPDATE I noticed I didn't shared the entire problem as I didn't knew it was because $timeout directive which causes the problem. Anyhow I updated my example.
Try defining $scope as a property in your controller class:
export class SandboxCtrl {
static $inject = ["$scope"];
constructor(private $scope: MyScope) {
}
}
Without going into much details the problem is solved by using bind to bind this to the function.
timeout(this.foo.bind(this), 1000);
timeout(this.foo, 1000); // does not work
This is be cause foo is an unbound function and the value of this will be driven by the caller.
Just use an arrow function 🌹
More
This is covered here https://basarat.gitbooks.io/typescript/content/docs/arrow-functions.html
i wrote a small controller where i declare a variable with var keyword which is not in scope. does it means that is private in scope ? see my code.
<div ng-app="myApp" ng-controller="myCtrl">
{{test}}
</div>
var app = angular.module('myApp', []);
app.controller('myCtrl', function ($scope) {
var test='test hello';
$scope.Operantion = 'hello';
$scope.GetData = function () {
abc();
};
function abc()
{
alert(test);
}
$scope.GetData();
});
the var test variable should be consider as private variable ?
if i declare a function with just function xxx() then it should be consider as private function. i am new in angular. so when testing code then many question is coming to my mind. so please guide me. thanks
Yes. var test and function xxx() should be considered "private" or, better, local data and function.
For reference see:
Angularjs scope
What is the scope of variables in javascript
Scope is an object, that the view can see and read values from it. By declaring a 'var', you are creating an object outside of the scope, but in the context of the controller function.
BUT the html, that comes with that controller via the ng-controller attribute for example, can only see properties of the scope of that controller.
import {Pipe, PipeTransform} from '#angular/core';
#Pipe({ name: 'reverse' })
export class ReversePipe implements PipeTransform {
transform(arg1) {
let data = '';
for (let i = 0; i < arg1.length; i++) {
data = arg1[i] + data;
}
return data;
}
}
so, I'm trying to use the 1.5 component feature, but coding with fat arrows. I am using babel to build the system
My component, stripped down to the bare minimum to show my problem, is thus:
angular.module('myApp')
.component('myComponent', {
controller: () => {
this.$onInit = () => {};
},
template: `<p>foobar1</p>`
});
when I try and load this component, I get an error complaining about
typeError: Cannot set property '$onInit' of undefined
so, when I look at the sources in chrome devtools, I see
angular.module('myApp').component('myComponent', {
/** #ngInject */
controller: function controller() {
undefined.$onInit = function () {};
},
template: '<p>foobar1</p>'
});
I would expect that I have done something very wrong, but can't see it ;)
anyone got any tips ?
thanks
Angular creates new instantion of controller for every component. In ES5 we dont have classes, so we pass construction function here.
But in es6 we have class, so you can use it instead
let myComponent = {
controller: myComponentController,
template: `<p>foobar1</p>`
};
class myComponentController{
constructor() {
this.answer = 41;
}
$onInit() {
this.answer++;
}
};
angular.module('myApp')
.component('myComponent', myComponent);
Pascal has also written something about it here: http://blog.thoughtram.io/angularjs/es6/2015/01/23/exploring-angular-1.3-using-es6.html
I am rewriting my AngularJS application using TypeScript. In my application I have used $scope to define variables and methods:
defectResource.defectByDefectId($scope.defectid).then(function (data) {
$scope.defect = data;
});
$scope.postDefect = function () {
defectResource.postDefect($scope.defect).then(function () {
$location.path('defects/' + $stateParams.itemid);
});
};
I can rewrite my controller something like this:
interface IDefectDetailModel {
}
class DefectDetailController implements IDefectDetailModel {
static $inject = ['$scope', '$stateParams', '$location', 'defectResource', 'entityProvider'];
constructor($scope: any, $stateParams: any, $location: any, defectResource: any, entityProvider: any) {
defectResource.defectByDefectId($scope.defectid).then(function (data) {
$scope.defect = data;
});
$scope.postDefect = function () {
defectResource.postDefect($scope.defect).then(function () {
$location.path('defects/' + $stateParams.itemid);
});
};
}
}
But if I understood correctly it is not good way. I need to create Interface and TypeScript class which will implement this interface. All my variables must be class variables (so $scope.defectid must be this.defectid) and all my $scope methods must be class methods (this.postDefect()).
Do I understood correctly? If I am using AngularJS with TypeScript the best way is not use $scope variables and methods and use only instance variables and methods (using this) ?
If I am using AngularJS with TypeScript the best way is not use $scope variables and methods and use only instance variables and methods (using this) ?
+100.
Key reason being that scope variables are susceptible to become disconnected due to angular's scope inheritance mechanism. Even without TypeScript it is recommended not to use scope varaibles and this is why the controller as syntax was created.
More on Angular controllers in typescript: https://www.youtube.com/watch?v=WdtVn_8K17E