Calling Templates on demand in SPA - angularjs

In my current SPA application, the index page shows Login form (default router) which doesn't have header & footer ,
When User Logs in account , router takes user to after login page and Header & footer are shown ( as per app requirement). My index.html looks like
<code>
<html>
<header ng-class="{hide:loginPage}">
</header>
<ng-view></ng-view>
<footer ng-class="{hide:loginPage}" ></footer>
</html>
</code>
but there is a problem. When User Routes to Default Login, fraction of a second The header & footer gets displayed. is there any best way to achieve result
Please guide how to fix this ?

I think you're looking for ng-cloak: http://docs.angularjs.org/api/ng.directive:ngCloak. Your header and footer are briefly flashing because the hide class isn't applied until the ng-class expression is parsed.

What I would do is to add an ng-include in my footer and header to selectively load what I need
Check this demo from angular page. It may help:
http://docs.angularjs.org/api/ng.directive:ngInclude

Related

different page structures with angular js ui-router

My be this is very basic, but I am really stuck here, here is my question :
I am using angular-ui-router with angular js
This is how my pages are structured (Left:Homepage, Right:Inner Pages (/about-us) ) :
Homepage (/)
Header
Content (100% width, one column)
Footer
so I create directives for Header, & Footer, and they will be common through out the site. & I load Content in ui-view, here is how my main template look like
<header-directive></header-directive>
<div ui-view></div>
<footer-directive></footer-directive>
And here are all the other pages strucure e.g (/about-us)
Header
Content Image/Map (100% width)
Content (75% Width)
Sidebar (25% Width)
Footer
So according to the Homepage structure above I need to load Content Image/Map, Content, and Sidebar in the UI-VIEW now, but Sidebar is common too, and that won't change on inner pages.
So the inner pages I only want to load Content Image/Map, and Content. Is there a way to achieve that ?
There is a very good blog post about UI-Router, http://www.funnyant.com/angularjs-ui-router/. Here the author creates similar example to yours, so I think it might help you.

AngularJS display login page on full screen

I have my angularjs app that has a topbar navigation, a left sidebar navigation and the rest is for the content (using data-ng-view I get different views).
My question is, if I have a view called login and a route that redirects me to the login page, how can I show that view actually in the full screen of the page?
Now if I navigate to http://applicationurl.com/#/login the view is like this:
I want it to look like this:
I cannot figure it out how can I achieve this in AngularJS?
The html is something like this:
<html>
<head>
</head>
<body>
<header>...</header> // top navigation bar
<div id="container">
<nav>...</nav> //left bar navigation
<div id="content">
<div id="wrap" data-ng-view="">
// here are loaded all the views ...
</div>
</div>
</div>
</body>
</html>
The correct solution would be to move your header/footer/sidebar into Angular Views and then use the Angular UI Router to build the pages with multiple named views where needed.
If you do not want to modify your code, it is not possible to achieve what you want to accomplish. By virtue of your login page being rendered by ng-view, it will be inserted within that tag on the page. You could hide the header and navbar with ng-hide set on some scope variable that would be set when the login page was rendered, and then the variable could be reset upon successful login/traversal to another page. This is a bit hacky, and is certainly not ideal, but is a quick and dirty fix. If you want to learn and do it correctly, Justin's suggestion is a great place to start.

Loader/spinner animantion while route is changing

How can I show a spinner or loader gif animation while route is changing from one to another.
I am using ng view like as follows:
<div ng-view class="view-animate">
</div>
I am loading templates from server and also inline. While the HTTP request is pending I need to show the spinner/loader... any snippets?
You can show and hide the loader when location change starts and is completed, respectively.
Here is a plunkr that I have created for this situation. This uses ui-router and is taken from one of the apps that I have created, so it may not be useful as-is, but it will give you an idea on how to approach the problem.
HTML Code inserted below just to keep SO happy...
<ui-view class="view"></ui-view>
<div loader="" class="ng-hide"></div>
I hope it helps.
Abhi.

AngularJS w/ noscript

I am attempting to create a SPA using AngularJS as the main view for my website. I'm using ServiceStack on the server-side and can therefore cleanly serve HTML or JSON requests depending on what's accessing it. My main concern is the use of script blockers, preventing AngularJS from rendering the page properly. So far my main way of working is to render static pages, and inject a small script that redirects to the AngularJS-powered pages if it detects if Javascript is enabled. This works great since every URL works fine when the user begins at the static pages, but I've ran into a couple of snags.
Browsing to a link which includes the "?View=SPA" breaks the page if JavaScript is disabled
This causes the first page loaded to be loaded twice.
I'm looking for an alternative, but so far I haven't found any clean solutions. I was thinking about including the "?View=SPA" as a POST variable, but I'm still iffy on that implementation.
Any thoughts?
Instead of redirecting to an other page, I would implement both cases in the same HTML File as follows:
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.min.js"></script>
<style>.hideIfNoScript {display: none}</style>
</head>
<body ng-app ng-init="msg = 'hello world'">
<input class="hideIfNoScript" ng-model="msg" />
<p class="hideIfNoScript">{{msg}}</p>
<noscript>
<p>Content without javascript</p>
</noscript>
<script type="text/javascript">
var myEl = angular.element( document.querySelectorAll( '.hideIfNoScript' ) );
myEl.removeClass('hideIfNoScript');
</script>
</body>
</html>
The CSS Class hideIfNoScript in the head section makes sure that all HTML Tags with this class are never shown to the user, if javascript is disabled.
The noscript tag shows the alternative content.
If javascript is enabled, the little script at the end of the body section makes those elements visible. And in this case, the contents of the noscript tag are hidden.
Browsing to a link which includes the "?View=SPA" breaks the page if JavaScript is disabled
Hide those links by default:
a[href*='SPA'] { display: none; }
This causes the first page loaded to be loaded twice
Use a cookie on a browser-check page which loads the first page in an iframe or redirects to it to avoid this.
References
Track Non-JavaScript Visits In Google Analytics

Jquery mobile ui-btn-active in navbar

I've been trying to get this to work for 4 days now, with no luck.
I have a very simple jquery mobile app.
The app has a header, content and footer.
The footer is being generated dynamically on the 'pagecreate' event because it is always the same and I don't want to have its HTML in every page.
So I do something like this:
$(document).delegate('[data-role="page"]', 'pagecreate', function (e) {
DrawHeader($(this));
DrawFooter($(this));
SetFooterEvents($(this));
SetActiveFooter($(this));
});
DrawHeader() and DrawFooter() simply prepent the header div to the page and append the footer div.
SetFooterEvents() sets the onclick events of the footer navbar buttons and SetActiveFooter() is SUPPOSED to set the ui-btn-active to the current active footer link.
To do this, I've added the data-active-footer attribute to the page div and the data-name attribute to the navbar elements. I'm searching for the current element according to the data-active-footer in the page and apply the ui-btn-active class.
function SetActiveFooter(page) {
page.children('div[data-role="footer"]')
.find('a[data-name="' + page
.attr("data-active-footer") + '"]').addClass("ui-btn-active");}
So far so good.
Now, say I've changed to a page and the navbar is lit (it has successfully recieved the ui-btn-active class), and I'm clicking on the previous page, the lit item in the navbar doesnt change back!
If i click on the the page again (ie: changed to second page [corrent lit], changed back to first page [second page is still lit], then clicked on first page again) it does light the navbar button.
What I found out was that jqm also changed the navbar of the previous page when I'm changing the navbar of the current page in the 'pagecreate' event.
I've tried to overwrite this behaviour using the 'pageshow' event, that is, trying to apply the ui-btn-active class to the current element in the navbar but the problem is that $(this) and e.currentTarget objects in the 'pageshow' event DO NOT CONTAIN THE FOOTER ELEMENT!!!
$(".ui-page").live('pageshow', function (e) {
alert($(this).children('div').length); // returns 2!
alert($(this).children('div[data-role="footer"]').length); //returns 0
alert($(e.currentTarget).children('div').length); // returns 2!
alert($(e.currentTarget).children('div[data-role="footer"]').length); //returns 0});
Any ideas?!
Thanks.
Before delving into more detail, please try adding .ui-state-persist together with .ui-btn-active
This makes sure active buttons stay active when you changePage and the footer is the same. Also make sure, all your footers have the same data-id attribute.
On a sidenote: check the latest blog post about upcoming features for jqm 1.1 - it will include a fetch link utility, which allows to ajax-update portions of a page. So you could use this functionality to grab and insert a footer on every page. I'm trying the same right now with a login form, which I need on every page.
Have you tried "ui-state-persist"?
<div data-role="navbar" data-iconpos="top">
<ul>
<li>Home</li>
<li>Favorite</li>
</ul>
</div>
I still dont know why but jqm moves the footer from page to page, eventhough I assign a new footer to each page.
Maybe because I set the same ID to all of them.
Anyhow, I used this workaround to solve the problem:
On the 'pagebeforeshow' event, I set the button I want active to all the footers in the documents. I've set a special data-name attribute to each navbar button, I give it the 'ui-btn-active' class after removing it from the rest of the items.
var $footers = $(document).find('div[data-role="footer"]');
$footers.find('a').removeClass("ui-btn-active");
$footers.find('a[data-name="' + page
.attr("data-active-footer") + '"]').addClass("ui-btn-active");

Resources