ng-if not working with simple javascript - javascript

ng-if is not working when I change the values through simple javascript function.My function is getting called but the changes in values cannot be seen in view. Please refer below code.
HTML
<div id="span" ng-app='MyModule' ng-cloak ng-controller="MyController">
<div ng-if="!bool">
This is for true
</div>
<div ng-if="bool">
This is False
</div>
{{bool}}
<br>
<input type="submit" ng-click = "myfunction('test')" value="ng-if button">
</div>
<input type="submit" onClick = "check1()" value="simple JS button">
JS
angular.module('MyModule', [])
.controller('MyController', function ($scope) {
$scope.bool = true;
$scope.myfunction = function (data) {
$scope.bool = !$scope.bool;
};
});
function check1() {
angular.element(document.getElementById('span')).scope().myfunction('test');
}
When I use ng-click button it changes value of bool changes, but same doesn't happens with simple JS button . Actually I am implementing Angular in a page that already uses jQuery, so I need to use simple JS button.
JS Fiddle : JS Fiddle

At first, ng-click is able to parse an angular expression.
Second, it handles the reference to the current scope and performs a call to $scope.$apply to notify any watchers to update. If you would add a call to angular.element(document.getElementById('span')).scope().$apply() in your function, it should work as expected.

Use $scope.apply . This is because angulars digest cycle will not know if your value changes outside of its scope like in a simple JS function.

Related

Difference between ng-init and onload for function invoke [Angular JS]

I am working on a angular application and have a scenario where i want to focus on a text field on page load. i have tried HTML5 autofocus but have to find an alternative solution for this since there is a browser compatibility issue for the same.
I am planning to invoke a function on page load which will focus on the input field i wanted. I have the following functions with Angular ng-init and onload to load the function.
I am not sure which method should i follow in the angular context as i am little confused between their difference.
onload
<body onload="focusOnInput()">
<form name="resetPasswordForm">
<input name="NewPassword" type="password"/>
</form>
</body>
<script>
function focusOnInput() {
document.forms["resetPasswordForm"]["NewPassword"].focus();
}
</script>
Angular ng-init
<body in-init="focusOnInput()">
<form name="resetPasswordForm">
<input name="NewPassword" type="password"/>
</form>
<script>
function focusOnInput() {
document.forms["resetPasswordForm"]["NewPassword"].focus();
}
</script>
</body>
onload is not in your angular context. onload function is a callback function on LOAD event of DOM.
your ng-init is in angular context. You need to use angular ng-init.
The ng-init function as shown in your code wont work as is. The function defined in ng-int should be in the angular context. your focusOnInput() isn't in the angular context . It's in javascript context.
if you like to use ng-init you'll need to inject $window into your controller and then use assign focusOnInput to your $scope and use that method in ng-init
something like this
angular.module().controller('TestController',['$scope','$window',function($scope,$window){
......
$scope.myNewFunction = $window.focusOnInput;
......
}])
and then use this myNewFunction in your ng-init.

compile ng-bind-html inside ng-repeat

I have a special template problem... I have a array of products, every products have a property "button_code", this property is a result in plain text of HTML laravel template with some angular code inside.
Actually im using a ng-bind-html="product.button_code" inside a and use this template inside a ng-repeat, the html code is correctly inserted in every repeat iteration, but the code is plain text, and I need to "wake up" the ng-controllers ng-clicks etc inside this html
I try with this:
var targets = $('.buy-button-container').toArray();
for (var target in targets) {
console.log($(targets[target]));
$compile($(targets[target]))($scope);
}
$scope.$apply();
But this make the code inside the container (all html code inserted in the ng-bind-html) dissapear of the DOM.
How i can do this?
PD: and yes, im forced to use these template in these product.button_code because special things...)
Thanks
EDIT: This is a piece of code i want to bind:
<button class="buy-link btn btn-default" data-toggle="modal" role="button" ng-controller="BuyController" ng-click="doProduct({'id':'8888','title':'testestest','price':13.99,'currency':'EUR''preorder_enabled':false,'crossedPrice':100,'stock':true,'short_desc':'bla bla bla.','lbonus':false,'bonus_txt':false})">
<span class="left">
<i class="fa fa-cart"></i>
<span itemprop="price">€13.99</span>
</span>
<span class="right">
{{GETIT}}</span>
</button>
Use the transclude function furnished as the second argument of the function created by the $compile service:
app.directive("compileBindExpn", function($compile) {
return function linkFn(scope, elem, attrs) {
scope.$watch("::"+attrs.compileBindExpn, function (html) {
var expnLinker = $compile(html);
expnLinker(scope, function transclude(clone) {
elem.empty();
elem.append(clone);
})
});
};
});
The above directive evaluates the compile-bind-expn attribute as an AngularJS expression. It then uses the $compile service to bind the evaluated HTML to the element. Any existing content will be removed.
Usage:
<div class="buy-button-container" compile-bind-expn="buttonCode">
<p>This Node disappears when expression binds</p>
</div>
Note that the directive uses a one-time binding in the $watch to avoid memory leaks.
The DEMO on JSFiddle
In order to make HTML render you have to use the following function:
$sce.trustAsHtml('<b>Your html</b>');
You will have to inject $sce into your Controller.
If you are doing this in a ng-repeat you will need a function in your controller that does this. Ex:
$scope.transformHTML = function(html) {
return $sce.trustAsHtml(html);
}
in your template...
<div ng-repat="foo in bar">
<div ng-bind-html="transformHTML(foo.html)"></div>
</div>
Anyway, I don't think that the "Angular" magic within your HTML will work.

ng-click not working with ng-if

Why does the second button not work, when ng-if is used?
I want to realize a button that is present only when the model value is set / not ""/ not null.
Template:
<input type="text" ng-model="blub"/>
<br/>
<button ng-click="blub = 'xxxx'">X</button>
<br/>
<button ng-click="blub = 'yyyy'" ng-if="blub.length">Y</button>
Controller:
angular.module('test', [])
.controller('Main', function ($scope) {
// nothing to do here
});
To play around: JSFiddle
Use ng-show Instead of ng-if. That should work.
Fiddle
It doesn't work because ng-if is creating a new scope and interpreting your blub = 'yyyy' as defining a new local variable in the new scope.
You can test this by putting the second button to:
<button ng-click="$parent.blub = 'yyyy'" ng-if="blub.length">Y</button>
However $parent is an ugly feature.
The button doesn't work because of the nested scope created by ng-if. The blub bound to the second button is not the same blub that's bound to the first one.
You can use ng-show instead of ng-if, since it uses its parent's scope, but that's just avoiding the problem instead of solving it. Read about nested scopes so you can understand what actually happened.
Also, check this out: fiddle
Try putting a magic dot on the variable
<input type="text" ng-model="bl.ub"/>
<br/>
<button ng-click="bl.ub = 'xxxx'">X</button>
<br/>
<button ng-click="bl.ub = 'yyyy'" ng-if="bl.ub.length">Y</button>
jsfiddle
you can use : [hidden]="!expression"

How do you show/hide an element on a click event from js code?

I used to use Jquery extensively. Now that I stumbled upon Angularjs, I am trying understand how it works and I have been really excited about the AutoMagic way it works. For example, am able to do the below process of hiding and showing few blocks just by using ng-click, ng-hide & ng-show.
<form id="signup-form" ng-submit="processForm()" ng-hide="showConfirm" >
<input type="text" name="user" ng-model="name">
<button type="submit" id="submit" ng-click="showConfirm = ! showConfirm">Submit</button>
</form>
<div class="col-md-12 confirmation" ng-show="showConfirm">
<h2 >Thanks alot for your feedback.</h1>
</div>
But, I am still wondering how can I do the same from code, say from a controller. In Jquery one way to do would be like:
$( "#submit" ).click(function() {
$(".confirmation").show();
$("#signup-form").hide();
});
And maybe if I want to validate the form I can use .preventDefault(); in Jquery and do something. How does all this work in AngularJs?
Just change the model value in your controller: showConfirm = !showConfirm;
This will update your view automatically using the ng-hide and ng-show directives you already have in place.
Better yet, call a scoped function like:
$scope.toggleConfirm = function() { showConfirm = !showConfirm; }
...and call that in your view using ng-click="toggleConfirm()" to keep your code DRY.

Dynamic variable for angular ng-click attribute

I am using the following way to use $scope variable ({{func}}() in this case) as function name in ng-click.
<button type="button" ng-click="{{func}}()">Call {{func}}</button></pre>
This works in angularjs-1.2.0rc3. See working plunkr here
Any future version from > 1.2.0rc3 throw this error
What's changed? How can I use the above syntax in current angular version?
Ok first of all I do not recommend such a usage for ng-click because angularjs itself do not support this, but if you still want to use it such a way here is your solution...
<button type="button" ng-click="$eval(functionName)()">...</button>
where
$scope.f1 = function() {
...
};
//name of function as a string
$scope.functionName = "f1";
this is what your are looking for and here is your PLUNKER example...
All I did was append scope to both variables
<form name="angular" ng-controller="Ctrl">
<button type="button" ng-click="{{scope.func}}()">
Call {{func}}
</button>
<label>Status: {{scope.status}}</label>
http://jsfiddle.net/bebold/TmKLY/1/
I wouldn't advise going this route for dynamic variable change, a better choice would be to create a directive and do the binding within the template:
A great explanation can be found HERE.

Categories