Delay displaying UI in cross platform app on ng-if - javascript

I have a cross platform app built using Monaca and AngularJS.
On some screens I display a generic view, and then display certain sections based on the outcome of some calculations/lookups using ng-if and ng-include.
E.g. for the Login screen, I display a generic view, while in my controller I check whether the user has logged in before. Depending on the outcome of this lookup, I either show a Welcome message OR prompt the user to Login.
Below is a abbreviated version of the generic login view.
<div>
<ons-page>
<ons-scroller >
<!-- Show if user not logged in -->
<div ng-if="!loggedIn">
<div ng-include="'login/login-details.html'"></div>
</div>
<!-- Show if user logged in -->
<div ng-if="loggedIn">
<div ng-include="'login/login-confirmation.html'"></div>
</div>
</ons-scroller>
</ons-page>
</div>
This is working fine but the issue is that the first ng-if is always shown - even just for a second - while the controller checks if the user is logged in and then sets the value of loggedIn. So the user always sees the login prompt until the controller returns true or false on the variable loggedIn.
The boolean value for loggedIn is just defined but not initialed in the controller. It only gets initiated once the lookup has been done.
How can I stop both the ng-include s from displaying till I know which one to display?
I can create another ng-if but it seems long winded and inefficient.

I would also use the ng-show and hide the items until they are evaluated using the ng-hide class, see below:
<div class="ng-hide" ng-show="!loggedIn">
<div ng-include="'login/login-details.html'"></div>
</div>
<!-- Show if user logged in -->
<div class="ng-hide" ng-show="loggedIn">
<div ng-include="'login/login-confirmation.html'"></div>
</div>

One method you can use is if loggedIn is null or undefined until you check weather the user is logged in, you can use a strict comparison operator === for true and false like so:
<div>
<ons-page>
<ons-scroller >
<!-- Show if user not logged in -->
<div ng-if="loggedIn === false">
<div ng-include="'login/login-details.html'"></div>
</div>
<!-- Show if user logged in -->
<div ng-if="loggedIn === true">
<div ng-include="'login/login-confirmation.html'"></div>
</div>
</ons-scroller>
</ons-page>
</div>
This would ensure that neither gets displayed until the outcome of your "lookup".
Another solution to the problem, depending on your choice of routing, would be to make use of ngRoute's or ui-router's resolve property. This way you can check if the user is logged in before the view is loaded.

Related

Appended html element inside angular directive is getting removed from DOM on changing view

I am developing a support chat system. Whenever a support staff clicks on support icon, support screen (staff-room.html) opens which has list of client waiting for request to be attended. Following is an extract of code from the above file
<md-list-item ng-repeat="client in clientChannelList | filter: searchText">
<div class="channel" layout="row" layout-align="center center">
<div class="md-list-item-text" layout="column" layout-align="center start" flex>
<h3 class="name">{{ client.senderName}}</h3>
<span class="site-name">{{ client.siteName}}</span>
</div>
</div>
<button chat-popup-box>Attend</button>
</md-list-item>
<div flex layout="column">
<md-toolbar class="background-transparent">
<div class="md-toolbar-tools" layout="row"></div>
</md-toolbar>
<md-divider></md-divider>
<div id="chat-popup"></div>
<md-divider></md-divider>
</div>
I have an attribute directive chat-popup-box (present in button element) which initialises on clicking of a button. Inside this directive I am creating an html element which creates chat pop up window and appending it with element having id chat-popup in the parent (staff-room.html).
var htmlelement = `<div class="popup-box chat-popup">Some stuff</div>`
var compiledElement = $compile(htmlelement)($scope);
var pageElement = angular.element(document.getElementById("chat-popup"));
pageElement.append(compiledElement);
Now the problem is whenever I am changing the state(navigating to any other module) and coming back, I am loosing the HTML which I have appended in <div id="chat-popup"></div> from DOM. Hence I am loosing chat window pop up.
So Before changing state view DOM was something like this
<div id="chat-popup">
<div class="popup-box chat-popup">Some stuff</div>
</div>
But after changing state and coming back to same state DOM is like this
<div id="chat-popup"></div>
While debugging I found out that directive is not being destroyed as even after changing state, flow was going inside the chat-popup-box directive but HTML which I have appended is getting removed from DOM. Is there a way to prevent that?
A good start might be to code your page in a more AngularJS-y way. The idea is that values are stored and manipulated in the various scope objects and component controllers. I'm not sure which part of the html is replaced, in your case, when you change to another module, but if you stay within the same app, your html will be re-rendered, including your button and functionality, but the popup will not appear until you press the button (again). If you want the popup to be open the next time you arrive on this page, you will have to store this fact in code somewhere. In AngularJS, services are typically used for this purpose.
You could do something like this:
<md-list-item ng-repeat="client in clientChannelList | filter: searchText">
(...)
<button ng-click="controller.changeActiveClient()">Attend</button>
</md-list-item>
<div flex layout="column">
(...)
<div id="chat-popup">
<div class="popup-box chat-popup" ng-if="controller.activeClient">Some stuff</div>
</div>
<md-divider></md-divider>
</div>
(better yet, create a component to hold your popup box)
Then, in your controller have something like this:
this.activeClient = staffRoomService.getActiveClient();
this.setActiveClient = staffRoomService.setActiveClient;
Or something; then, create the staffRoomService to store your active client. Anyway, do read up on scopes, components, and "the AngularJS way". It will make your life better and more fun. https://docs.angularjs.org/guide/concepts

Unable to scroll to a div element using hash in Angular app

I have read here and here that a page can be scrolled to a specific element using just a hash selector and a id attr.
But for some reasons I am unable to do it in my Angular application. Can this be due to the usage of routing (angular-ui-router) in my app.
What I am trying to do is moving to a specific section of one of my page, which by the way are loaded in to a state using routing.
I have :
<div class="nav_panel">
<a class="nav_links" href="#footer">Footer</a>
</div>
and
<div class="homeFooter" id="footer">
<div class="social_icons">
<span class="gplus"></span>
<span class="fb"></span>
<span class="twitter"></span>
<span class="whatsapp"></span>
<span class="youtube"></span>
</div>
</div>
on the same template.
Is there a way I can make it work with routing (if at all that matters) as well or am I doing something wrong here ?
Based on this answer, you can add the _targetattribute to the <a>tag.
For your need, value on _target is self. It's an attribute compatible with all recent browser, that will redirect you to the link in the same frame as the user click (useful for SPA e.g.)
Go to the footer
<div id="footer">Welcome to the footer</div>

how to use <div ng-view = ""> mulitple times

In my application I have an index.html file where i have loaded all the required scripts and the body contains am empty ng-view whose content will update based on the route url.
The first page is a landing page where I'am showing a button to the user, clicking on which am showing Login Page, by changing the path value of $location.
On Successful login a dashboard page should come where header, sidebar footer area is going to be fixed and only the center area is going to be changed based on the menu clicks which is there in header section, by changing the route value
so the center area i declared as
when am trying to load the dashboard.html page it is going to infinite loop and when am removing the center div which is nothing but an empty view , my view is rendering fine. So the problem is with using the
Can anyone suggest me whether my understanding is corect ??
If yes please suggest me how to achieve my requirement...
index.html
<div class="row">
<div data-ng-view=""></div>
</div>
dashBoard.html
<div class = "row">
<header div here>
<div>
<sidebar div>
**<div data-ng-view = ""></div>** which is not working
</div>
<footer div here>
</div>
I have provided the html code
Thanks
What you're trying to do is not supported by the default router. You can try ui-router which supports multiple and nested views. You can see an example here http://plnkr.co/edit/7FD5Wf?p=preview. The index.html contains the main view.
<body ng-controller="MainCtrl" class="container">
<div ui-view></div>
</body>
Inside contacts.html there is another view
<h1>My Contacts</h1>
<div ui-view></div>
Try checking the difference between route provider and state provider.
Here's a link to ease your search.

Subviews for elements in AngularJS

I want to have an single-page App (AngularJS) with following views:
Login
Main View
Now the Main-View should have different "elements":
- Toolbar
- Main Content Div
- 2 Sidebars
Can I handle all this elements as a subview? I would like to have a .html Template for each of these "elements".
Thank you very much!
Do not split into two base html. That is not good design for Angularjs apps and it will be creating problem while running test cases (unit or end-2end test cases).
Please look the below code. Here "userLoggedIn" is a $rootscope variable for loading necessary block based on authentication.
<div ng-include="'views/common/loginHeader.html'" ng-show="!userLoggedIn"></div> <!-- loginHeader -->
<div ng-include="'views/common/userHeader.html'" ng-show="userLoggedIn"></div> <!-- userHeader -->
<div class="container" ng-view></div> <!-- body -->>
<div ng-include="'views/common/footer.html'"></div> <!-- footer -->
After authentication, you can set boolean flag or object to that variable.
$rootScope.userLoggedIn= true
(or)
$rootScope.userLoggedIn= {"name":"john smith", "settings":[{}]}
In logout controller, you can set false for hiding authentication containers and redirect to login page.
$rootScope.userLoggedIn= false;

AngularJS - Handle repeated fragments like Header and Footer

I have been trying to implement the header / footer in an Angular JS App. I was thinking of adding these as ng-include in the main index.html. However this would have worked if the header and footer are static pages. My case is slightly different... In Login page no header / footer is shown. Other pages depending on whether you are logged in or not, you have to show "Welcome user [ logout] " or "Welcome guest [ login ]".
I save the login information in the rootScope as well as set a boolean $rootScope.isLoggedIn on login. The biggest problem seems to be that the whole ng-include is not refreshed on a logoff. Hence divs with ng-show hide directives will not hide/show on change. Somebody suggested using ng-switch - it also behaves the same way.
If I move the header code inside individual views then everything is fine.
A similar question is here: Refresh header page in angularjs
Use a controller in the header/footer, as ivarni suggested. An example from an (experimental) app of my own:
In the index.html, the header will display a dynamically generated menu, login/logout etc:
<div id="navbar" class="navbar navbar-inverse navbar-fixed-top"
x-ng-controller="NavbarCtrl" x-ng-include="'app/main/navbar.html'"></div>
The NavbarCtrl builds the appropriate scope for the app/main/navbar.html template. The template would be as follows (taking into account your needs - and irrelevant details removed):
<div class="navbar-inner" x-ng-if="showHeader">
<div class="container">
<div>
<ul class="nav">
<li x-ng-repeat="menuEntry in menuEntries">
<a x-ng-href="#{{menuEntry.path}}">{{menuEntry.display}}</a>
</li>
</ul>
</div>
</div>
<div x-ng-if="userData.loggedIn">
Wellcome {{userData.userName}}!
<a x-ng-click="logout()">Logout</a>
</div>
<div x-ng-if="!userData.loggedIn">
<a x-ng-click="login()">Login</a>
</div>
</div>
So the entire markup is hidden depending on the showHeader scope variable. It creates the menu dynamically (menuEntries). And depending on userData.loggedIn, the appropriate Login/Logout message.

Categories