AngularJS 1.5 calling a method from another in component's controller - angularjs

I am using angularJS 1.5 component in my application. sample code of component's controller as bellow:
function testController()
{
var vm = this;
activate(); // this will be called on first load on component.
vm.testMethod = function ()
{
return "test Method";
}
function activate()
{
console.log(vm.testMethod());
}
when I execute this I am getting error
TypeError: vm.testMethod is not a function.
I know I can create a local function to controller not appending vm., however, in my need, I have a vm.testMethod() used in template to get return some text, which is working properly. e.g.
--template code
{{$ctrl.testMethod()}} // This works properly and display 'test Method' on page.
Due to some reason, I am trying to call vm.testMethod() inside another method e.g. activate(), however getting an error mentioned above?
May I know if am missing anything or trying something which is not possible.

Your issues does not have anything to do with Angular :-)
Your activate function is hoisted because it is a function declaration. That why you can call it "before your wrote it". BUT, vm.testMethod is a function expression and won't get hoisted.
Here is a super simple example that shows the issue your having:
var vm = {};
console.log(vm.hello);
vm.hello = function () {};
console.log(vm.hello);
I would recommend you to read this article for a better understanding of how expressions and declarations work in JavaScript. Also, in order to prevent this from happening again you should follow this advice from John Papa:
Always write function declarations at the bottom of your controller and assign them at the top when you defined your vm variable.

Related

AngularJS $window.open throws "Cannot read property 'arguments' of null"

I'm creating a simple web page where i display a button which execute this code
$window.open(link, "_self");
The link variable is a simple telegram link for a channel, but this is not the problem, the problem, as the question say itself, is about arguments variable in $window.open.
This in my opinion is strange because when i logged in the console $window.open function, i received this output:
function pbWindowOpen() {
lastBlockCaller = {
caller: arguments.callee.caller,
args: arguments.callee.caller.arguments
};
try {
return newWindowOpenFn.apply(this, argument…
At this point, should not i see an argument variable inside this function? How could i solve this problem?
Passing some arguments could resolve my problem? If yes, there's an answer about why i'm having arguments null?
I've also tried with window.open but nothing changes, always the same problem
That shouldn't happen if you are running your code in a browser (in other env you may have some initialized variable window representing something else), $window is a wrapper in top of var currWindow = $window.self || $window.window and then do a perform of callong open(...) function. Hence, you neither using the native javascript code badly in a angular context, and again that would be easily mock-ableif we mock $window and create a property call self or window inside it. So it will work in the application, and will also be testable.

Service Method called 5 times from Angular Controller

This one has me confounded. I have looked far and wide and am out of ideas. In my searching, I discovered that one of the common reasons for multiple function calls on load is if you have a controller defined in routes and via the ngController directive. Checked this - I do not use ngController. I also checked my routes - seem in order. There are no $watch functions that could be causing $digest issues. This function is called one time, at the bottom of the function, and the console.log is logged out 5x...EVERY TIME. I have even set a $timer function and it still calls it 5x. Have tried creating a variable to only run if it hasn't been run before but it seems like it's all happening with the getQuotas() method. Any help would be greatly appreciated!
function getQuotas ()
{
console.log('getQuotas'); //This logs out 5x
UserService.getQuotas()
.then(function(res)
{
if (res.data.success)
{
quotaData = res.data.data;
getQuotas_success();
return true;
}
else
{
getQuotas_failure();
return false;
}
}, function (err)
{
getQuotas_failure();
return false;
});
}
getQuotas(); //Function is called here.
Solved it! I'm hopeful this will help others. There was a custom attribute directive on each of 4 input fields on this page. That particular directive was using the same controller as the page itself. So the controller was getting loaded a total of 5 times. Fortunately for me, this directive is now deprecated but I would probably redo it by either creating a directive-level controller and using the 'require' attribute in the directive's return object, pointing to the page-level controller, OR just have the data that needs to get passed between the page-level controller and the directive go through a service.

Adding a method to Restangular

I am new to Restangular. Since its already been used in the project I am currently working on, I need to learn about it. I am trying to setup a new method, which upon called, calls a rest call and return nothing.
for ex: I have factory like this in
//app.js
factory('events', ['Restangular', function (Restangular) {
return Restangular.all('events');
I want to add a method ackAll by extending 'events'. I have tried like this.
RestangularProvider.extendModel('events', function(event) {
event.ackAll = function() {};
return event;
});
I want to call this method whenever user login. I am not sure how to do that. Whatever i tried, i am getting error as "ackAll is not a function ". I am sure I am missing very easy part but I am not sure what it is.

using data from a callback from Ebay api in Angularjs

I am trying to use the ebay api in an angular.js app.
The way the api works by itself is to pass data to a callback function and within that function create a template for display.
The problem that I am having is in adding the data returned from the callback to the $scope. I was not able to post a working example as I didnt want to expose my api key, I am hoping that the code posted in the fiddle will be enough to identify the issue.
eBayApp.controller('FindItemCtrl', function ($scope) {
globalFunc = function(root){
$scope.items = root.findItemsByKeywordsResponse[0].searchResult[0].item || [];
console.log($scope.items); //this shows the data
}
console.log($scope.items); //this is undefined
})
http://jsfiddle.net/L7fnozuo/
The reason the second instance of $scope.items is undefined, is because it is run before the callback function happens.
The chances are that $scope.items isn't updating in the view either, because Angular doesn't know that it needs to trigger a scope digest.
When you use the Angular provided async APIs ($http, $timeout etc) they have all been written in such a way that they will let Angular know when it needs to update it's views.
In this case, you have a couple of options:
Use the inbuilt $http.jsonp method.
Trigger the digest manually.
Option number 1 is the more sensible approach, but is not always possible if the request is made from someone else's library.
Here's an update to the fiddle which uses $http.jsonp. It should work (but at the moment it's resulting in an error message about your API key).
The key change here is that the request is being made from within Angular using an Angular API rather than from a script tag which Angular knows nothing about.
$http.jsonp(URL)
.success($scope.success)
.error($scope.error);
Option 2 requires you to add the following line to your JSONP callback function:
globalFunc = function(root){
$scope.items = root.findItemsByKeywordsResponse[0].searchResult[0].item || [];
console.log($scope.items); //this shows the data
$scope.$apply(); // <--
}
This method tells Angular that it needs to update it's views because data might have changed. There's a decent Sitepoint article on understanding this mechanism, if you are interested.

angularjs factories seem to be created lazily

Today I am experiencing something really odd which I have never read about.
Just think the debugger is on the "var startDateOfWeek..." line.
With my mouse pointer I hover over the wizardDataFactory object. This object is not instantiated when there is not the line of code "var x = ..." which comes later...
WHY is that? I have never read something about factories are somehow lazily instantiated?
Well I do not want to complain because actually thats a good thing. Do not instantiate when the factory is unused in code.
Can someone please share a link where I can read about that?
'use strict';
angular.module('iplanmylessons').service('periodService', function ($q, $http, datetimeFactory, weeklyDataGridViewModelFactory, wizardDataFactory) {
this.getWeeklyPeriods = function (schoolyearId, firstDayOfWeek) {
var startDateOfWeek = datetimeFactory.getFirstDateOfWeek(firstDayOfWeek);
var endDateOfWeek = datetimeFactory.getLastDateOfWeek(firstDayOfWeek);
var x = wizardDataFactory.transform();
return [];
};
});
Your understanding is not correct.
wizardDataFactory is initialized as soon as any other component requests it as a dependency.
The hovering undefined is probably due to a browser error.

Resources