Angular on PhoneGap, ngView changes same page multiple times generating $digest error - angularjs

I am trying to port a web app to mobile using Cordova PhoneGap. It works more or less as expected, except for the ngView directive.
[OLD PROBLEM]
When I change page, the new page overlays on the old one, mixing their elements. I solved this with an asynchronous bootstrap of Angular, after the deviceReady event.
[UNSOLVED PROBLEM]
I can see on Xcode also a huge use of memory during run-time. At the home page I see about 90MB of use. If I go to the user page (much more heavy), memory consumption is about 200MB. If I come back to the home page, memory increases instead of coming back to 90MB.
I noticed that when I open a new page, its controller is initialized multiple times generating the $digest loop error. In fact when I go to the home page, the log writes 'PAGE OPENED!!' 10 times
I don't have pending setTimeout or setInterval.
I guess that when a scope is destroyed, also its controller does.
This is how I use ngview:
index.html
<body ng-cloak class="ng-cloak" style="overflow-y: auto;">
<div ng-view></div>
...
</body>
app.modules.js
angular.module('myApp', [...])
.config(function($routeProvider){
$routeProvider
.when('/home',{
templateUrl: 'app/home.html',
})
.when('/user',{
templateUrl: 'app/user/profile.html',
});
})
home.html
<div id='home_page' ng-controller="homePageController as ctrl"
ng-style="{'background-image':'url('+{{ctrl.image}}+')'}">
<div>
this is the home page
</div>
</div>
homePageController.js
.controller('homePageController', [function($scope)
{
self.image="/img/img.png";
console.log('PAGE OPENED!!');
this.pageClosed = function()
{ $scope.$destroy(); }
}]);
It works well on the browser, I can't understand why I can't smoothly change pages in the app.
Thank you

Related

Controlling html outside the ngview when page changes

I have a single page angular application and this is my index.html file:
<html ng-app="myApp">
...
<div id="bash">...</div>
...
<div id="menu">...</div>
...
<div ng-view></div>
...
</html>
Then I have a home controller with its template and an about us controller with its own template as well. And I want their templates to come up in the ng-view which is happening already but I want the #bash to only come up when the url ends with /home and hide when the url ends with anything else.
I can't do that through the home controller because it's outside the ng-view
and I can't do this through a normal JS file as well because the application loads once.
I can go through each controller and have a js function that changes #bash's css and turns display into false but I'd rather just have a condition in one place and I'm sure it's doable. Any ideas?
Why couldn't you do that from the home controller?
<div id="bash" ng-show="bashShown()">...</div>
...
$scope.bashShown = function() {
return $location.path().endsWith('/home');
};

how to switch ng-view to normal page

See image
=>Layout1 master page which include ng-view in that i used angular routing.
=>Layout2 login.cshml page when I tried to call login page
http://localhost:1395/admin/home/Login
this login page included in ng-view which i donot want
its total different page Login.cshtml
I called this page like
Log out
when I tried url directly in address bar like http://localhost:1395/admin/home/Login
it works fine see image
but i tried from master panel to login page it shows wrong see first image
example code
master.cshtml
<html>
<body>
<div>Layout 1</div>
<div ng-view></div>
</body>
</html>
contact.html
<div ng-controller="contactcontroller">
Contact Page
</div>
help.html
<div ng-controller="helpcontroller">
Help Page
</div>
routing code
var app = angular.module("myApp", ["ngRoute"]);
app.config(function($routeProvider) {
$routeProvider
.when("/admin/home/contact", {
templateUrl : "contact.html",
controller: "contactcontroller"
})
.when("/admin/home/help", {
templateUrl : "help.html",
controller: "helpcontroller"
})
});
Login.cshtml
<html>
<body>
<div>Layout 2</div>
///Login code
</body>
</html>
when I call this url admin/home/help and admin/home/contact pages included in ng-view but when I call admin/home/login i donot want this include in ng-view it is separate header and footer . I want call as separate page
Thanks in advance
It is hard to understand this, but I'll take a shot at answering the question.
Your problem is probably unrelated to angularjs, what it seems to me is, that you're probably using ASP.NET MVC and your Login action is rendered inside the master layout. Basically you need to render the page without the template. See this question and answers there: Razor View Without Layout
I will also point out that angular is used for single page applications and it is hard to mix angular and ASP.NET MVC routing. You should probably decide which routing you will use. Sure, you can use .NET and initialize angular in every page, but I don't recommend this. If you can, build all your pages in angular and then then use ASP.NET Web API as a back-end.
Also you don't need to use ng-controller attribute when you use routing and specify controller.

Use ui-view as the template for state inside ui-router instead of an external template

I have an app that is currently using the angular ui-router module dependency. The only aspect of the ui-router that I'm currently employing is the ability to apply/modify $stateParams to $scope and vice versa so the URL can change the way data is displayed in the controller to a user on arrival (i.e. url?param=something will filter the data by something).
I have the following in my app.config to set the state:
$stateProvider
.state('root', {
url: '/?param',
templateUrl: 'template.html',
controller: 'listController',
params: {
param: {
value: 'something',
squash: true
}
}
});
On my homepage, template.html successfully loads when the app is instantiated as such:
<div ng-app="myApp">
<div ui-view>
</div>
</div>
However, I have reached a roadblock and realize that calling the template from within templateUrl isn't going to work, as this app is being built inside another framework and therefore needs to be called from within the homepage itself to access its full capabilities.
Being a noob at AngualrJS, I was wondering if anyone can tell me what the best way is to accomplish this while still keeping the logic of $stateParams and other ui-router capabilities intact for the future.
For instance, could I just remove the templateUrl parameter from my state and call the controller directly inside the ui-view like this:
<div ng-app="myApp">
<div ui-view>
<div ng-controller="listController">
do something
</div>
</div>
</div>
I also looked into changing the entire logic from using ui-router to simply using the $location service but I'm wondering if there is a way to accomplish this without needing to over-do everything.

AngularJS - How to load ng-view based on the URL?

I have been following the AngularJS tutorials on CodeSchool.
So I have views/index.html which contains all of my boilerplate code that is identical for each page. Then my templates for each page are in views/templates/ which I want included in the index.html page. So when the home page loads, it loads the views/index.html and includes the views/templates/index.html.
views/
index.html
templates/
index.html
contact.html
about.html
Currently I have
<div id="menu">
<a id="menu_home" href="/#/index" ng-click="menu.set(0)" ng-class="{current:menu.isSet(0)}">Home</a>
<a id="menu_hire" href="/#/hire" ng-click="menu.set(1)" ng-class="{current:menu.isSet(1)}">For Hire</a>
<a id="menu_info" href="/#/info" ng-click="menu.set(2)" ng-class="{current:menu.isSet(2)}">Info</a>
</div>
<div id="main">
<ng-view></ng-view>
</div>
which works great. So only the required html is requested and inserted into the page.
But my problem is that the URL doesn't change in the browser. So if a user went directly to mysite.com/contact it wouldn't work. How can I load the page correctly if the mysite.com/contact or mysite.com/about pages are accessed directly?
I have also got it working using the ngRoute module, but the same issue remains when a user goes directly to a page.
Thanks.
You should use ngRoute and $routeProvider similar to the following.
var navigationRoutes = angular.module('navigationRoutes', ['ngRoute']);
/**
* Load routes for navigation using ngRoute
*/
navigationRoutes.config(function ($routeProvider) {
$routeProvider
.when('/index', {
templateUrl: 'app/components/index/index.view.html',
controller: 'IndexCtrl'
})
.when('/contact', {
templateUrl: 'app/components/contact/contact.view.html',
controller: 'ContactCtrl'
})
.otherwise({
redirectTo: '/dashboard'
});
});
This way you can also specify a different controller based on the URL.
UPDATE
In your index page if you add -
<div class="view">
<div ng-view></div>
</div>
To your main index.html page the the contents of the $routeProvider selected file will be shown within this div. You just need to make sure that you add the tag for the controller.js files in the index.html page.
You will need to make these settings in the web server to redirect all urls to your index page where you load your angular app which in turn will handles the routes

angularjs specific page without ng-incude

I design my pages with angularjs like following
<html>
<head></head>
<body>
<ng-view></ng-view>
<ng-include="'footer-tpl.html'">
</body>
</html>
so whenever navigate to any pages will just change the ng-view, but now I want to have a
page without the <ng-include="'footer-tpl.html'">. How to do that?
I just realized you can use ngHide with ngInclude:
http://plnkr.co/edit/BBpfQBRgtr7tAK6iFRTR?p=preview
HTML
<div ng-include="'footer.html'" ng-hide="hideFooter"></div>
JavaScript
angular.module('test', []).controller('test', function ($scope) {
// TODO set this to true to hide the footer, if you don't set it, it stays visible
//$scope.hideFooter = true;
});
When this patch for ngIf makes it into a release, you can use it in place of ngHide. It seems like it'll prevent footer.html from even being loaded if you hit the right view, but I'm not totally sure on that.

Resources