HTML load before my js function executes - javascript

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>

Related

Checking for defined functions in nested directives

When passing a function into a directive which then is passed into a nested child directive the function is always considered defined when checked in the scope of the child directive regardless if it is passed in or not in the parent directive.
Is there a better way to either pass in function pointers or check if they are defined when dealing with nested directives.
plunker
<body ng-app="myApp">
<div ng-controller="myController">
<dir1"></dir1>
</div>
<script type="text/ng-template" id="dir1">
<div>
<dir2 fun="fun()"></dir2>
</div>
</script>
<script type="text/ng-template" id="dir2">
<div>{{fun()}}</div>
<div>{{funDefined()}}</div> <!-- always true-->
</script>
</body>
var app = angular.module('myApp', []);
app.controller('myController', function($scope) {
$scope.fun = function() {
alert("function");
};
});
app.directive('dir1', function() {
return {
scope: {
fun: '&'
},
templateUrl: 'dir1'
};
});
app.directive('dir2', function() {
return {
scope: {
fun: '&'
},
link: function(scope, elem, attrs) {
scope.funDefined = function() {
return angular.isDefined(attrs.fun);
};
},
templateUrl: 'dir2'
};
});
If you set debugger inside your scope.funDefined method of dir2 you'll see that attrs.fun equals string "fun()". That's because you take raw value from attributes. And since it's a not empty string it'll always give you true.
Here is updated plunker
There's no elegant way I know to get what you want. Like it was mentioned before this line:
angular.isDefined(attrs.fun)
performs check on string so it will return true every time fun attribute is defined. And in your dir1 directive template you have <dir2 fun="fun()"></dir2> so fun is obviously defined (and it's string). If you take a look at angular's sources:
case '&':
// Don't assign Object.prototype method to scope
parentGet = attrs.hasOwnProperty(attrName) ? $parse(attrs[attrName]) : noop;
// Don't assign noop to destination if expression is not valid
if (parentGet === noop && optional) break;
destination[scopeName] = function(locals) {
return parentGet(scope, locals);
};
break;
you'll see that presence of the attribute will always result in some function assigned to the scope ($parse returns function even for string that doesn't make much sense).
So the only solution I can think of is to perform check in the first level directive (it's possible there since attribute is really undefined) and have two <dir2> tags (with and without fun attribute) - one always excluded using ng-if. Something like this. Again, I know, its ugly solution.
One side note - Angular's source also shows that scope property will not be set if there's no attribute and binding is optional (using &?) - then you can check scope.fun value instead of attrs.fun - some may find it more elegant.
The best way I could find is based in what #xersiee commented in another answer. The idea is to make the scope parameter optional in the parent directive and then use angular.isUndefined(scope.$parent.$eval(attribute.myFun)) to check if the function was passed or not. This is not explained in the official documentation... I wonder why.
As other people has mentioned, this solution is far from ideal because using scope.$parent is an anti-pattern, but again, this is the best option I could find.
Plunker with this solution: http://plnkr.co/edit/SUUMae?p=preview

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.

Setting a $scope variable in view does not work unless I call a function to do it

If you have an html file where you toggle a boolean on click, sometimes i'm able to do it directly in the view and sometimes I have to create a function in my controller to toggle the boolean. Why does this work sometimes but not all the time?
Only works sometimes..
<div ng-click="myVar = !myVar">Toggle</div>
Always works..
<div ng-click="updateVar();">Toggle</div>
...
$scope.updateVar = function() {
$scope.myVar = !$scope.myVar;
};
If you have not set $scope.myVar initially, myVar and $scope.myVar are not the same variable. Use...
<div ng-click="$scope.myVar = !$scope.myVar">
...to ensure you are always accessing the same variable.

How to pass scope variable in ng-init using AngularJS

I have problem passing the variable declared from the scope to ng-init:
so far I have something like this:
$scope.x = '10';
<div ng-controller = "controller" ng-init="function(x)">
How do I pass x var from the scope inside ng-init function?
A lot of people will tell you you shouldn't do this (as mentioned in the docs here: https://docs.angularjs.org/api/ng/directive/ngInit).
As for actually doing it....
<div ng-controller="controller" ng-init="x = x">
Maybe this one can help you:
$scope.x = '10';
<div ng-controller = "controller" ng-init="x">
If you wanted to push a value in using the ng-init i would use something like this
Js code
angular.module("app",[])
.controller("ctrl",function($scope){
$scope.x = "this will be replaced"; //not really needed
$scope.initialize = function(bar){
$scope.x=bar;
}
})
and html
<div ng-app="app" ng-controller="ctrl" ng-init="initialize('your value')">
If you want to execute a function on a tag where you have a controller, why not simply run the function in the controller's constructor (i.e. function)?
Not everything has to be in the markup.
JS:
angular.module(...).controller('MyController', function ($scope) {
$scope.myFunction($scope.x);
})
HTML:
<div ng-controller="MyController"></div>

Object not a function in AngularJS

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) { ... }

Categories

Resources