Object not a function in AngularJS - javascript

I have a controller that seems to be misbehaving. I have removed all the other code that works to make this short:
Controller:
'use strict';
angular.module('AppliedSiteApp').controller('CarouselCtrl', function ($scope) {
$scope.nextImage = function() {
console.log('hi');
}
});
View:
<div class="carousel" ng-controller="CarouselCtrl">
<ul class="nav">
<li ng-click="prevImage()"><</li>
<li ng-click="nextImage()">></li>
</ul>
</div>
Every time I click the button in the browser it says: 'TypeError: object is not a function' or 'no method replace'. What am I doing wrong?

Are you still having a problem with this?
I ran into the same issue. The problem for me was that the function name in the controller and view was the same name as a form I was using in the same view.
Changing either the form name or the function name fixed the error for me.

Something is wrong with the way you are wiring things I believe. I usually use this scaffold:
angular.module('AppliedSiteApp.controllers', []).
controller('CarouselCtrl', ['$scope', function($scope) {
$scope.nextImage = function() {
console.log('hi');
}
}]);
The first argument to controller is the name, and the second is an array. In the array, you define what services you are injecting into your controller, then you define the callback function with the injected services as parameters.

When creating a new module you need to specify a second parameter (its dependencies). If you have none, simply pass an empty array.
angular.module('AppliedSiteApp', [])...
Your example could access an existing module (that's when you don't specify the second argument), but then there's probably some code missing to spot the error (or I'm just blind).

try the following definition of controller
var AppliedSiteApp = angular.module('AppliedSiteApp', []);
function CarouselCtrl($scope) {
$scope.nextImage = function() {
console.log('hi');
}
}

I agree with the other responses that it's an issue with your wiring. Try this fiddle as an example: http://jsfiddle.net/reblace/7fVQR/
Declare your outer div like this:
<div ng-app="app" ng-controller="MainController">
And then your controller like this:
var app = angular.module('app', []);
function MainController($scope) { ... }

Related

HTML load before my js function executes

If my controller, I have a function to set the true to a variable.
function setShow() {
return this.isShow === 'Foo';
}
My this.isShow is 'Foo'
In my template, I have <div ng-if = "vm.setShow()"> Hi </div>
But it seems like that HTML load before my js function executes? I do not know how to handle this case. I often face this problem.
You can try for this:
In angularjs:
But $timeout service should be inject into your controller.
$timeout(function(){
// write your logic here
},100);
This will fire when your HTML document is ready.
Call your function inside the timeout.
Or in JavaScript you can use the:
Settimeout(function(){
//write here
},100);
From ng-if:
The ng-if directive removes the HTML element if the expression
evaluates to false.
If the if statement evaluates to true, a copy of the Element is added
in the DOM.
your function doesn't evaluate to true and that is why the div isn't show. try returning true from the function.
Edit: now that you edited your post, the problem seems to be the function isn't in $scope and there is a strange vm in ng-if that probably shouldn't be there.
You don't have the setShow function declared in the $scope. I think the ng-if directive doesn't find the function and it interprets as false.
Try
angular.module("myApp", []).controller("myCtrl", function($scope) {
var isShow = "Foo";
$scope.setShow = function () {
return isShow == "Foo";
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp" ng-controller="myCtrl">
<div ng-if="setShow()"> Hi </div>
</div>

Override Angular Directive link

I have limited knowledge of Angular so please bear with me. I am in a situation where I can only modify one js file which is included BEFORE all of the Angular stuff. There is a directive that is causing a problem, yet I can not modify it directly. So I've tried to override it by adding the snippet below in a document ready block:
app.directive('selectionChange', function($rootScope){
return {
priority: 1,
terminal: true,
link: function(scope, el, attr) {
console.log('works');
};
};
});
I can see this directive added to the end of the invokeQueue, but it is never executed. How do I get this attached? Thanks!
UPDATE:
Sorry, let me try to clarify. Problem is, the original directive continues to fire, but the newly attached one does not (tested by using console.log and alert). The markup is something like this:
<html>
<head>
...
<script src="[the file I can modify].js"></script>
...
</head>
<body>
...
<script src="angular.js"></script>
<script src="directives.js"></script> // here is where the existing selectionChange directive is defined
...
</body>
</html>
Here's a plunker
$(function () {
var app = angular.module('app');
app.config(function ($provide) {
$provide.decorator('badDirective', function ($delegate) {
var badDirective = $delegate[0];
var link = function (scope, element) {
element.text('good');
}
var originalCompile = badDirective.compile || function () {};
badDirective.compile = function () {
originalCompile.apply(badDirective, arguments);
// compile returns link fn, directive 'link' property will be ignored anyway
return link;
}
return $delegate;
});
});
})
Doing it on 'ready' state (e.g. jQuery ready implementation) is the right thing. This way the code will be launched before the bootstrapping process (it will be queued on 'ready' via ng-app as soon as angular.js is loaded).
bad directive is just badDirective service internally which contains an array of DDO (because there can be several directives with the same name). And it can be decorated, as any other service.
Link function can be defined with either link or compile (it can return link) DDO properties. The second overrides the first, so always stick to compile when decorating directives.
In the file you can modify create a script tag with a (reference/definition) to your new directive and place that tag at the bottom of the body right after the troubled directive definition. By being the last one defined you'll ensure that is your directive the one rendered.

Using this instead of $scope inside controller

I am trying to follow style guide for angular and there wrote we should use this insted scope...
Styleguide
Could someone explain me when I am able to use this?
Here is my try..... What I am doing wrong?
I am trying to toggle form....
here is my html code:
REPLY
<a href="#" ng-click="formEdit(x)" ng-if="x.formEditShow" >CLOSE</a>
With classic $scope I would do like this inside my conroller :
$scope.formEdit = function(data){
data.formEditShow = !data.formEditShow;
}
But with this it should look something like this(but don't work):
var vm = this;
vm.formEdit = formEdit;
function formEdit(data){
data.formEditShow = !data.formEditShow;
}
Anyone can help me to understand this?
When you are using this(context) in controller instead of $scope, you must use controllerAs while defining html on page to access controller variables. Whenever you wanted to use variable bounded to this on view you could use alias of your controller. Below you can see vm is alias of controller.
ng-controller="myController as vm"
Then while accessing controller method an variable inside ng-controller div you need to use alias of your controller like ng-click="vm.formEdit(x)"
HTML
REPLY
<a href="#" ng-click="vm.formEdit(x)" ng-if="x.formEditShow" >CLOSE</a>
Assuming your controller is named FormController.
First step
The first step is to declare the route (or the ng-controller value if you are not using a router) as such:
FormController as form // name it semantically instead of a generic name
Due to the above configuration, angular will alias as form the instances of FormController.
HTML template
Then adapt your html template according to the alias you gave (form). I modified your html to keep only the essential part about the question. We are calling the functions form.reply and form.close.
REPLY
CLOSE
Controller declaration
According to what we wrote above, our controller should look like that:
myApp.controller('FormController', function () {
var vm = this;
vm.reply = function () {
// ...
}
vm.close = function () {
// ...
}
}
Notice the var vm = this; line? Theoretically we could get rid of this line, and store the functions reply and close in the this object. But depending of the context, this does not refer to the same object. In a callback function this would not refer to the controller but to the callback function. That's why we are caching the this that refers to the controller. We usually name this reference vm for viewmodel, as a controller controls a view.

Integrating non-Angular code?

I'm developing a Cordova/PhoneGap app, and I'm using the $cordovaPush plugin (wrapped for PushPlugin) to handle push notifications.
The code looks something like this:
var androidConfig = {
"senderID" : "mysenderID",
"ecb" : "onNotification"
}
$cordovaPush.register(androidConfig).then(function(result) {
console.log('Cordova Push Reg Success');
console.log(result);
}, function(error) {
console.log('Cordova push reg error');
console.log(error);
});
The "ecb" function must be defined with window scope, ie:
window.onNotification = function onNotification(e)...
This function handles incoming events. I'd obviously like to handle incoming events in my angular code - how can I integrate the two so that my onNotification function can access my scope/rootScope variables?
Usually, you'll wrap your 3rd party library in a service or a factory, but in the spirit of answering your particular scenario...
Here's one possibility:
angular.module('myApp').
controller('myController', function($scope, $window) {
$window.onNotification = function() {
$scope.apply(function() {
$scope.myVar = ...updates...
});
};
});
A couple of things to notice:
Try to use $window, not window. It's a good habit to get into as it will help you with testability down the line. Because of the internals of Cordova, you might actually need to use window, but I doubt it.
The function that does all of the work is buried inside of $scope.apply. If you forget to do this, then any variables you update will not be reflected in the view until the digest cycle runs again (if ever).
Although I put my example in a controller, you might put yours inside of a handler. If its an angular handler (ng-click, for example), you might think that because the ng-click has an implicit $apply wrapping the callback, your onNotification function is not called at that time, so you still need to do the $apply, as above.
...seriously... don't forget the apply. :-) When I'm debugging people's code, it's the number one reason why external libraries are not working. We all get bit at least once by this.
Define a kind of a mail controller in body and inside that controller use the $window service.
HTML:
<body ng-controller="MainController">
<!-- other markup .-->
</body>
JS:
yourApp.controller("BaseController", ["$scope", "$window", function($scope, $window) {
$window.onNotification = function(e) {
// Use $scope or any Angular stuff
}
}]);

accessing angularjs from javascript or else

I am learning angularjs and a bit confused. I am creating an angular module and controller functions like this:
var mapApp = angular.module("mapApp", []);
mapApp.controller("mapController", function($scope) {
$scope.save = function() {
//do domething
};
});
And I have other functions out of the controller.
function onMapClickEvent(e) {
//do domething
}
When map clilcked, I want to populate angular save function. Is this possible.
I asked this because sometimes we need to work with more then one API. AngularJS and Google Maps API. One API function need to populate other API.
You can cast DOM element to Angular element in this way:
angular.element(DOM)
And get the current scope of DOM by invoking scope()
angular.element(DOM).scope()
Then you can access any member of this scope, in your example: save()
I implemented a simple example, you could try it:
HTML
<div ng-controller="myCtrl">
<button id="testBtn" onclick="onClick(this)">test</button>
</div>
JS
angular.module("app",[])
.controller("myCtrl",function($scope){
$scope.angularWorldFunction = function(){
console.log("message from angular world");
}
});
function onClick(target){
angular.element(target).scope().angularWorldFunction();
}
Here is jsFiddle demo
Hope this helpful.

Categories

Resources