Applying conditions in ng-show and ng-hide - angularjs

I am new to Angular JS, I got stuck up with this code, While I am reading the tutorials, I got stuck up with this code on Angular JS. Please help me on that.
More particularly how 'AfterClicked' is working in controlling the visibility of the DIV elements.
HTML Code:
<!DOCTYPE html>
<html ng-app="myModel">
<head>
<title>Begin with Angular</title>
<meta charset="utf-8" />
<!-- Adding the Bootstrap style sheet-->
<link href="Styles/bootstrap.min.css" rel="stylesheet" />
<!-- Adding the Angular File-->
<script src="Scripts/angular.js"></script>
<script src="Scripts/MainM.js"></script>
</head>
<body>
<div ng-controller="myController as control">
<div ng-hide="AfterClicked">
{{control.title}}
click To Edit
</div>
<div ng-show="AfterClicked">
<input ng-model="control.title">
Done Editing??
</div>
</div>
</body>
</html>
JS Code:
/// <reference path="angular.js" />
var myApp = angular.module("myModel", [])
.controller("myController", function () {
this.title = "Welcome to Angular",
this.AfterClick=0
});
It's working fine, The thing that i got stuck up is "AfterClicked", How it's working in ng-show, ng-hide and ng-click in anchor tags.
Please help me on that..!!

Updated answer:
When you don't define an object in AngularJS controller code but use it in the template, Angular creates that object and it's assigned empty string value. So, in this case, even though you did not assign any value to AfterClicked in JS code, it was created by Angular and set to ``. This evaluates to false and the div is hidden.
You can check the value in this fiddle: http://jsfiddle.net/5DMjt/12053/
Firstly, couple of mistakes in the code.
1.There is a typo with AfterClicked in JS code.
2.Since you are using the myController as control syntax, ng-click on the anchor tag should use control.AfterClicked and not AfterClicked.
Now in JS code, AfterClicked is being set to 0, which evaluates to false in JS.
In the ng-hide="AfterClicked" code, AfterClicked evaluates to false and hence angular hides the div.
In the anchor tag code ng-click="AfterClicked=!AfterClicked",means that on click of anchor tag, the expression "AfterClicked=!AfterClicked" is evaluated ,which negates AfterClicked.

Related

How to use AngularJS in jsf page

I want to learn AngularJS to use in JSF pages. This is purely learning purpose.
I tried simply add AngularJS code inside the jsf. But seems it doesn't identify the AngularJS code. it simply out put the same My first expression: {{ 5 + 5 }} in the browser.
my jsf page
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js">
</script>
<body>
<div ng-app="hi" >
<p>My first expression: {{ 5 + 5 }}</p>
</div>
</body>
</html>
Can anyone help me how to get the output of the AngularJS expression within the jsf page? or show me some direction
UPDATE
My Actual intention is to get some json from Managebean or from another jsf page and populate here. but for that as testing I tried to create a dummy json structure. but still jsf doesn't identify AngularJS component. It's simply print
My first expression: {{ 5 + 5 }}
Browser console prints MyFirstAng.xhtml:24 Uncaught TypeError: app.conntroller is not a function
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<body>
<div ng-app="myAPP" ng-controller="customerctrl">
<p>My first expression: {{ 5 + 5 }}</p>
<!-- <ul>
<li ng-repeat="x in myData">
{{x.Name + ', ' + x.Age}}
</li>
</ul>
-->
</div>
</body>
<SCRIPT type="text/javascript">
var app = angular.module('myAPP',[]);
app.conntroller('customerctrl', function($scope){
// $scope.myData=[{Name:'jani',Age:'32'}];
});
</SCRIPT>
</html>
Ok, I found the issue. It was a typo in the app.controller. I had type additional "n". it worked. Thanks for all so far guiding me to spot the issue. I thought I am missing to include some AngularJS library or something.
In order for angular to initialize ng-app="hi" there needs to exist a module with that name. Otherwise you should be seeing an exception thrown in browser dev tools console. Please note console errors when developing javascript apps
Either include a module with that name or remove the name from the attribute and just use ng-app
Either paste this
var app = angular.module('hi',[]);
in your script or make the ng-app="" ... Your choice.
If you specify anything in the ng-app then you have to make a module as given above by me. Otherwise just dont specify anything in the ng-app i.e. ng-app="".
At a later stage when you want to make a controller then you can make a module.. For now its best left empty.

angular js dynamic directive passing model attribute

I knwo that are many relevant posts about how creating dynamic directive mapping in angular but I cannot find anything similar in my case. As the description suggests I am trying to make a dynamic directive where depending the value of an object attribute the html is changed. I simplified my problem to this case:
I have a list of object "Widget" which has an attribute name 'type'. I want depending on the type attribute of this list to render html depending on the attribute. To be more specific the Widget.type can have 3 values for example: widget1,widget2 . So in my case I want the directive to return the file widget*.html. (widget1.html for widget type "widget1" etc). Though I pass the argument to the directive using attributes, the value is not evaluated and the string widget.type is return.
Can you help me?
Thx in advance.
app.js file:
var app = angular.module("MainCtrl", []);
app.controller("myCtrl", function($scope) {
function Widget(type){
this.type=type;
}
$scope.widgets=[];
$scope.widgets.push(new Widget('widget1'),new Widget('widget2'),new Widget('widget3'));
});
app.directive('widget', function() {
return {
restrict: 'E',
scope: {
obj: '='
},
templateUrl: function(element,attr){
//console.log(attr);
console.log(attr.obj);
return attr.obj+'.html';
}
}
});
index.html file:
<!DOCTYPE html>
<html ng-app="MainCtrl">
<head>
<meta charset="utf-8" />
<title>AngularJS Plunker</title>
<!-- css -->
<link rel="stylesheet" href="style.css" />
<!-- utilities -->
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.js"></script>
<!-- angular module file -->
<script src="script.js"></script>
</head>
<body ng-controller="myCtrl">
<div ng-repeat="widget in widgets">
{{widget.type}}
<widget obj='widget.type' ></widget>
</div>
</body>
widget1.html file:
<div class="widget">
widget1:{{widget.type}}
</div>
widget2.html,widget3.html are the same
Notice the console output in the directive.
I created a plunker so it's easier to notice the problem:http://plnkr.co/edit/ulBSQQrqpSV9g3BNGRhO?p=preview
First example with your directive: http://plnkr.co/edit/XAXy5RGLnvUZIoRj5xAs?p=preview
Secone example without your directive:
<div ng-repeat="widget in widgets">
<!--{{widget.type}}-->
<div ng-include="widget.template"></div>
</div>
Note: additional property in your Widget-object. Easier to handle.
First one is not as beautiful as the example without the directive, becaue your scope-variable of the directive has to be the same as the variable in your templates ('widget'). I like the second example much more.

How to hide and show templates rather than destroy and reinject them everytime

I am using ui-router and Named views. it works flawlessly but it doesn't suit my purpose. I don't want the templates to be injected everytime i click on the menu item but only the first time it is clicked after application is loaded. The remaining times, it should simply hide the template and show the template that is currently active for a menu click. when coming back to the original menu click, it should just do ngShow="true" for the hidden template and hide the current one. Is that possible to do without editing the cleanupLastView() in the angular-ui-router?
If i comment out the cleanupLastView(), it simply keeps on injecting templates and does nothing to older templates. So both end up showing. Tried to debug the cleanupLastView() but i couldn't figure out what variables are available to me there so i could re-show what ever is clicked a second time rather than inject again.
index.html
<!DOCTYPE html>
<html lang="en">
<head ng-app="myApp">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="style.css" rel="stylesheet">
<script type="text/javascript" src=".lib/angular-1.3.0/angular.js"></script>
<script type="text/javascript" src="./angular-ui-router.js"></script>
<script type="text/javascript" src="./modular/ct-ui-router-extras.core.js"></script>
<script type="text/javascript" src="./modular/ct-ui-router-extras.dsr.js"></script>
<script type="text/javascript" src="../timerService.js"></script>
<script type="text/javascript" src="../dataService.js"></script>
<script type="text/javascript" src="app.js"></script>
</head>
<body>
<div class="navbar navbar-default navbar-static-top" role="navigation">
<ul class="nav navbar-nav">
<li ng-class="{active: $state.includes('main')}"><a ui-sref="home">Main</a></li>
<li ng-class="{active: $state.includes('files')}"><a ui-sref="files">Files</a></li>
</ul>
</div>
<div>
<div ui-view="pane"></div>
</div>
</div>
</body>
</html>
app.js
var myApp = angular.module("myApp", [ 'ui.router', 'ct.ui.router.extras.dsr']);
app.config(function ($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise("/");
$stateProvider
.state('main',
url:"/main",
deepStateRedirect: true,
views : {
pane: {
templateUrl : 'tpl.pane-0.html'
},
}
)
.state('files',
url: '/files',
deepStateRedirect: true,
views : {
pane : {
templateUrl : 'tpl.pane-1.html'
},
'first#files' : {
templateUrl : 'tpl1.first.html',
deepStateRedirect: true
},
'second#files' : {
templateUrl : 'tpl1.second.html',
deepStateRedirect: true
},
},
)
});
tpl.pane-0.html
<div>
<input type='text'></input>
</div>
tpl.pane-1.html
<div >
<div data-ui-href='first'></div>
<div data-ui-href='second'></div>
</div>
tpl1.first.html
<div>
<input type='text'></input>
</div>
tpl1.second.html
<div>
Second
</div>
This is the simplified code of my app. it works to do the multiple named views but fails at deepStateRedirect which seems to be the one associated with nav bar type of templates rather than(?) Sticky. Is that correct? I added the param deepStateRedirect: true to allthe views being injected but to no avail. if the tpl1.first.html's input text box is written and the view switched to main, and come back, there is no text to be found in the input box. What am i doing wrong?
Yes, you can do this but it requires some custom work.
Change the state so that it uses an empty template.
In the state's controller check if the document already contains the HTML for the view (use a unique ID).
If required, use the $template cache and $compile to create the original template view and append it to the document body.
In the template, you can use ng-show="isState_expression | isState" expression to toggle the visibility of the template.
Basically the ui-routes work the same as before, but you're handling the compiling of the template yourself. Once it's in the DOM (not inside the ui-view). You can just leave it there to be handled by ng-show.
I don't recommend using resolve on the state since it's going to become a static state.
Here's the manual on $compile:
https://docs.angularjs.org/api/ng/service/$compile
Here's a tutorial on $compile:
http://www.benlesh.com/2013/08/angular-compile-how-it-works-how-to-use.html
Here's a stack answer on $compile:
Compiling dynamic HTML strings from database
Why doesn't it suit your needs? Do you need to preserve the states when they are not shown?
If so, perhaps you should look into UI Router Extras Sticky States. It allows you to preserve the $scope of a state and not create/destroy it every time. This would be better than trying to reinvent the wheel.
Take a look at the sample.

Puzzled by CSS selector to trigger controller

I'm having trouble understanding how an attribute selector can be used to restrict the scope of a controller. Here's the minimal controller code:
import 'package:angular/angular.dart';
#NgDirective(
selector: '[my-controller]',
publishAs: 'ctrl'
)
class MyController {
String foo = 'fooooooooooooo';
}
main() {
ngBootstrap(module: new Module()
..type(MyController));
}
And here is the view that uses that controller:
<!DOCTYPE html>
<html>
<body>
<div>
<!-- DOES NOT WORK. MAKES SENSE. -->
<p>Outside ng-app: {{ctrl.foo}}</p>
</div>
<div ng-app>
<div my-controller>
<!-- WORKS. MAKES SENSE -->
<p>Inside my-controller div: {{ctrl.foo}}</p>
</div>
<!-- WORKS. WHY? It is outside the div with the my-controller attribute -->
-->
<p>Outside my-controller div: {{ctrl.foo}}</p>
</div>
<script type="application/dart" src="main.dart"></script>
<script type="text/javascript" src="packages/browser/dart.js"></script>
</body>
</html>
Predictably, the {{ctrl.foo}} code does not work outside the element with the ng-app. Also predictably, {{ctrl.foo}} works inside <div my-controller>. But I don't understand why it works outside <div my-controller>. Any ideas?
The issue is that you are using NgDirective not NgController. NgDirective does not create its own scope and hence the leak. Switching to NgController should solve the issue.
I believe the issue lies in the fact #NgDirective does not create it's own scope...
Try #NgComponent and move your:
"Inside my-controller div: {{ctrl.foo}}"
into its template property.

Why doesn't AngularJS update the views for model containers?

In the following Angular application, why don't {{myForm}} and {{myForm.userTypeInput}} update when the userTypeInput model is changed.
<!doctype html>
<html ng-app>
<head>
<script src="http://code.angularjs.org/1.0.6/angular.min.js"></script>
<script>
function Ctrl($scope) {
$scope.userType = 'guest';
}
</script>
</head>
<body>
<form name="myForm" ng-controller="Ctrl">
userType: <input name="userTypeInput" ng-model="userType">
<tt>userType = {{userType}}</tt><br>
<tt>myForm = {{myForm}}</tt><br>
<tt>myForm.userTypeInput = {{myForm.userTypeInput}}</tt><br>
</form>
</body>
</html>
The first line updates according to the changes made in the model, but the last couple of lines always remain the same:
myForm = {"userTypeInput":{}}
myForm.userTypeInput = {}
while I expected them to change according to the value I type in userTypeInput.
The name attribute of the element does nothing in terms of how angular treats a DOM element, the ng-model, ng-app, and ng-controller are the only parts in your HTML (along with the data bindings) that Angular will recognize. Since angular doesn't look at the name attribute when resolving variables for binding it doesn't update the other two, Angular is only looking at variables on the scope.

Resources