AngularJS - Variables in Layout to swap login/my account sections - angularjs

Just getting into AngularJS coming from a Zend Framework 2/jQuery way of working.
My layout.html within Zend Framework would contain something like:
<html><body>
<div id="topNavigation" class="nav nav-fixed">
<?php
if ($this->identity()) :
?>
<button id="logoutBtn">Log out</button>
?>
else:
?>
<input type="text" name="username" />
<input type="password" name="password" />
<button>Login</button>
<?php
<?php
endif;
?>
</div>
<?php
// The content from each ViewAction
echo $this->content
?>
<footer>This is the common footer text.</footer>
</body></html>
Now I'm converting this to AngularJS I understand the index.html is the layout with ngView directive pointing to template files for each view.
How do I get variables into my layout to switch logged in state? If you can't really control the layout, where do I hold the code that maintains logged in state, cause I don't see anywhere for global code.
My angularJS index.html layout file is currently like the above:
<html><body>
<div id="topNavigation" class="nav nav-fixed">
<button id="logoutBtn">Log out</button>
<input type="text" name="username" />
<input type="password" name="password" />
<button>Login</button>
</div>
<div ng-view></div>
<footer>This is the common footer text.</footer>
</body></html>

The best place is probably in $rootScope which, since all controller's scopes inherit from this, can be thought of as 'global'.
I see in your index.html above, though, you haven't specified a controller. You would need to add a controller (probably in 'body'), and in that controller, add the login info to the $rootScope.
Once you have a variable in your $rootScope (say 'isLoggedIn'), then you can use the ng-show and ng-hide directives to determine what subsets of the DOM you want displayed.

Related

How can make a label not visible as soon as a user types in an input using AngularJS?

I have a html as follows
<input ng-required="true" ng-model="Email" type="text" value="">
and i have a div as follows:
<div id="invalid" style="display: none">
<strong><i class="mycustomclass" ></i>Invalid</strong>
</div>
How can i make it that as soon as the user types in the input then the div is no longer visible or hidden using Angularjs. I know i need to use ng-show or hide but i cant seem to figure out how to put it together with the input ?
If you are using components it will look like this:
<div id="invalid" data-ng-hide="$ctrl.Email">
<strong><i class="mycustomclass" ></i>Invalid</strong>
</div>
If you are using old controller style:
<div id="invalid" data-ng-hide="Email">
<strong><i class="mycustomclass" ></i>Invalid</strong>
</div>

Angular - Form and $pristine does it work with nested inputs?

I have the following form.
A couple of issues I am facing:
1 - I'm unable to check for $pristine on the form with console.log($scope.myFirstForm.$pristine); I'm seeing the error: `cannot read property '$prestine' of undefined'.
Based on my code is this actually possible i.e. to use when the input fields are nested within several div tags?
2 - To clear the fields I'm currently having to do each field individually, is it possible to do at the form level which clears all input fields with that?
<form name="myFirstForm">
<div class="row">
<div class="large-12 medium-12 small-12 columns">
<input ng-model="main.pToAdd" type="text"/>
</div>
</div>
<div class="row homeTopBackgroundColor">
<div class="large-12 medium-12 small-12 columns">
<h5>Room</h5>
</div>
<div class="row large-12 medium-12 small-12 columns">
<input ng-model="main.o1ToAdd" type="text" />
</div>
</div>
<div class="row">
<div class="large-12 medium-12 small-12 columns">
<input ng-model="main.opToAdd" type="text"/>
</div>
</div>
</form>
SOLVED:
In my routes file I was specifying a controller (so 2 controllers on one page). I was checking on the child scope not the parent hence not being found. So I removed the setting of a controller in the routes file and just specified it in required places of HTML.
First the form included in the controller will automatically be in the scope of that controller.
Inputs inclosed in the form are part of the form no matter how nested it is. (use the name attr to be able to validate them.. assign errors and states to them)
Setting the form to pristine state will clear even the validations .. setting the main object in your case to {} will clear all the input fields.
`cannot read property '$prestine' of undefined -> can be because you are calling it in the controller before the form is assigned in the view. try the same thing on a click of any button should not give the same answer.

angular 1.3.6 ng-messages are present regardless of value

I'm trying to incorporate some of the new features of 1.3 into our app. I have a form and couldn't seem to get ng-messages to work. So I put it in a plunker and I still seem to be doing something wrong. My view looks like this:
<form name="profileForm"
ng-submit="profile.submit(profileForm.$valid)"
novalidate>
<input type="text" name="favoriteNumber"
ng-model="profile.number"
required ng-minlength="5" />
<div class="errors" ng-messages="profileForm.favoriteNumber.$error">
<div ng-message="required">this is required</div>
<div ng-message="minlength">this is too short</div>
</div>
<input type="submit" value="Save" />
</form>
I expected to see only one ng-message tag at a time, but both are present when the page loads.
At least I expect the message to go away as their validation criteria are met, but no matter what I type in the input, both messages are always present. It is as if I didn't include the ng-messages script at all.
What am I doing wrong here?
var app = angular.module("demo", ['ngMessages']);
include ngMessages module in you application module as a dependency.
plunker

router::url doesn't work in the same controller

I have this form:
<div id="buscador">
<form action="<?php echo Router::url(array('controller'=>'categorias','action'=>'buscar'));?>" name="form_search" id="form_search" method="post" >
<input type="text" name="search">
<input type="submit" value="Buscar" class="buscador" id="boton_buscar"/>
</form>
</div>
It works fine in all controllers except when you are using the controller "categorias"... in that case, the result is this: http....Categorias/buscar/Buscar
Any idea why this happens?
The problem was present elsewhere, I didn't consider that when clicking the button inside the View "buscar", then JS acts on that click (and this generates the buscar/Buscar problem)

CakePHP - How to use login form as Element

I am learning CakePHP. I am trying to develop a login system, but instead of using the login.ctp as a user/view, I wish I could use it as a element because I have the login form in many other pages. How can I declare within my users_controller that my function login() will use just the element. I said that because I used $this->render('/elements/login') and it did work. However, my element login.ctp was within my default.ctp layout, thus, I had two login forms. One was the element and the other as my content in my default.ctp layout.
Thanks!
Layouts are for the "greater" markup of a page: head and meta information, includes, "footer" stuff like your analytics. Generic content pointers go in the middle - so there's no need to mark anything as specific as a form in a layout unless you really do want to include that form on every page that uses that layout.
It sounds like you either called $this->render() in your view? $this->render() is a controller method. $this->element is the view method.
Or you called $this->element('/elements/login'); from in your login.ctp view? That would mean the controlller rendered the default login.ctp view, which called the login.ctp element.
And thus you saw two. To fix:
To return something other than the default view associated with an action (such as your login snippet), call $this->render('name/of/whatever'); as the last line of the controller method. It will return the view you specify; set will pass whatever variables to it, just like a regular view call and if you want to get fancy, specify the layout as ajax and watch the magic start like $this->render('/elements/login', 'ajax').
If you need to call several elements in a single view file, use the method $this->element('/fancy/nav/whatever'); you can also place them in layouts as appropriate (navigation, etc.)
HTH. :)
I had the same thing done to my project and this is what I did.
Basically, I created a new loginElement.ctp and placed it in the element folder. I create new sets of HTML code that would fit the layout where I wanted to use this element and the loginElement.ctp <form would then submit the data to login action in the users_controller.
If you need to and when I get home later, I can post my exact code here.
==================================== EDIT =========================================
These are the codes I used:
First of all you will notice that the action in the login form points to /login.
I have that setup in my /config/routes.php file as such
Router::connect('/login', array('controller' => 'users', 'action' => 'login'));
Then the other codes are below
/views/elements/thinlogin.ctp
<div id="login">
<form method="post" action="/login" accept-charset="utf-8" class="formBox">
<fieldset>
<input type="hidden" name="_method" value="POST" />
<div class="form-col">
<label for="username" class="lab">Username/Email</label>
<input name="data[User][username]" type="text" id="UserUsername" class="input">
</div>
<div class="form-col form-col-right">
<label for="password" class="lab">Password</label>
<input type="password" name="data[User][password]" id="UserPassword" class="input">
</div>
<div class="form-col form-col-submit">
<input name="" value="Login" class="submit" type="submit">
</div>
<div class="form-col form-col-check">
<label><input name="remember" class="checkbox" type="checkbox">Remember me on this computer</label>
</div>
</fieldset>
</form>
</div>
/views/pages/home.ctp
<div id="home_top_right_top">
<?php
if (!$this->Session->check('Auth.User.id'))
{
echo $this->element('login/thinlogin');
}else{
echo $this->element('login/loggedin');
}
?>
</div>

Resources