AngularJS controller reloading - javascript

I'm running a AngularJS webapplication with ionic.
I got a headpage where I see a list of articles. When I click on this you'll get a seperate page with tabs.
When i go from the headpage to a tab-page the controller loads for the first time.
$scope.selectArt = function(artikel) {
api.setCurrItem(artikel.artnr);
$state.go('tab.voorraad');
}
The controller is will be loaded.
app.controller('ArtikelsCtrl', function($scope, $state, $location, api, artikels) {
console.log("loaded");
};
I have a backbutton where I can go back to the headpage.
When I click on a item the selectArt function will be loaded again but the 'ArtikelsCrtl' will not be loaded again.
App.js
$stateProvider
.state('artikels', {
url: '/artikels',
templateUrl: 'app/artikels/artikels.html',
controller: 'ArtikelsCtrl'
})
.state('tab', {
url: '/tab',
abstract: true,
templateUrl: 'app/_shared/tabs.html'
})
.state('tab.voorraad', {
url: '/voorraad',
views: {
'tab-voorraad': {
templateUrl: 'app/voorraad/voorraad.html',
controller: 'VoorraadCtrl'
}
}
})
Anyone got an idea why the controller don't load on the 2nd time?
It looks like the page just hide and show up again on $state.go.

Controllers are initialised once per view. When you pass the controller option you are specifying how it is constructed. Changing view leaves the controller in existence.

ui.router.state.$state
$state.go(to, params, {reload : true})
I hope it can help you.

Related

How to change state of angular ui-router website when bootstrap carousel 'next' or 'previous' button is pressed?

I have a very basic angular ui router module set up for a website I am working on. It is as follows:
var myApp = angular.module('main', ['ui.router']);
myApp.config(function($stateProvider){
$stateProvider
.state('home', {
url: '/home',
templateUrl: './home_screen.htm'
})
.state('nowshowing1', {
url: '/nowshowing1',
templateUrl: './now_showing.htm'
})
.state('nowshowing2', {
url: '/nowshowing2',
templateUrl: './now_showing.htm'
})
.state('comingsoon1', {
url: '/comingsoon1',
templateUrl: './now_showing.htm'
})
.state('comingsoon2', {
url: '/comingsoon2',
templateUrl: './now_showing.htm'
})
.state('concessions', {
url: '/concessions',
templateUrl: './home_screen.htm'
})
.state('freemovies', {
url: '/freemovies',
templateUrl: './FreeMovies.htm'
})
.state('pictures', {
url: '/pictures',
templateUrl: './pictures.htm'
})
.state('contributors', {
url: '/contributors',
templateUrl: './contributors.htm'
})
.state('about', {
url: '/about',
templateUrl: './home_screen.htm'
});
});
I have a bootstrap carousel and my ui-view inside the carousel. Right now, my website works when using my bootstrap navbar to navigate to each page, where each page is an html page, but also a 'slide' in the carousel. I want the user to be able to use the arrow buttons on the side of the screen to switch to the next and previous 'slide' or page.
I am very new to angular and angular ui router, and I have not been able to find useful documentation on how I might not only access the current, next, and or previous states in my stateProvider, but how to call the method that will access those from my html.
I tried a controller like this:
myApp.controller('StateChangeCtrl', function($scope, $state){
$scope.previousState = function(){
console.log('Previous State!', $scope);
}
});
Then tried to call previousState() onclick of the arrow buttons in the carousel, but got a not defined error.
How/where would I access the current, next, and or previous state of the website if my pages go in the order of how I declared them in the stateProvider, and then how would I call the function from html that would do that?
If I could even access the current state somewhere, I can hardcode what the next and previous states will be (I assume I'd use $state.go() to change states) because I know the order of my html pages and there are not a ton of them...

Ion-View does not refresh (Angular UI-Router)

I have this classic ionic view refresh problem:
.state('app', {
url: '/app',
abstract: true,
templateUrl: 'templates/menu.html',
controller: 'AppCtrl'
})
.state('app.menu', {
url: "/menu",
views: {
'menuContent': {
templateUrl: "templates/headmenu.html"
}
}
})
.state('app.menu.media', {
url: "/media/:MediaType",
views: {
'media-tab': {
templateUrl: "templates/tabs/media.html",
controller: "MediaCtrl"
}
}
}).state('app.settings', {
url: "/settings",
views: {
'settingsContent': {
templateUrl: "templates/settings.html",
controller: "SettingsCtrl"
}
}
})
The app start from 'app.menu.media' state, I click on 'settings', the view is loaded, but the problem occurs when I try going back to 'app.menu.media' state, the view is not refreshed (I still have the 'settings' view)
One of the solutions suggested by other devs is using ui-sref-opts="{reload: true, notify: true}" inside a <a ui-sref="app.menu.media" ...> ..</a> tag, but it's not smooth, the users feel like if the app freezes for a short time, and the same goes for the javascript solution: $state.go('app.menu.media', {}, {reload: true});
I know that the controller is not loaded when it is in the same state, but in this example we have different controllers: "MediaCtrl" and "SettingsCtrl", so why we have this problem? Is there any clean solution to fix this problem?
Edit:
This problem occurs even if I'm disabling the cache: $ionicConfigProvider.views.maxCache(0);
After Debuging the app, I found that the problem was not related to cache, but it doesn't mean that enabling the views cache will not affect the app, disabling the cache was important for my case.
So the problem was related to the fact that I was using the same state "app" for both 'media' and 'settings' views, with different view names: "settingsContent" for "app.settings" and "menuContent" for "app.menu". So I had to add these two Ion-nav-views to the template Url linked to the "app" state, which is "menu.html", juste like this:
<ion-nav-view name="menuContent"></ion-nav-view>
<ion-nav-view name="settingsContent"></ion-nav-view>
So when I go back to "app.menu.media" state, the view is indeed loaded, but the "settings" view is still there, and it is hiding my new requested view "media"!
So what I did to fix this issue is to use the same Ion View name:
.state('app.menu', {
url: "/menu",
views: {
'THESAMENAME': {
templateUrl: "templates/headmenu.html"
}
}...
....
.state('app.settings', {
url: "/settings",
views: {
'THESAMENAME': {
templateUrl: "templates/settings.html",
controller: "SettingsCtrl"
}
}
And inside menu.html, I deleted the two previous lines, and replaced theme with:
<ion-nav-view name="THESAMENAME"></ion-nav-view>
I hope this could help someone

Access url params in master controller

My application has two controllers. I have a pageCtrlwhich I use to handle my navigation and sidebar. I also have a calendarCtrl for handling the data on my page. This controller is configured as shown below:
$stateProvider
.state('calendar', {
url: '/calendar/:category/:competition/:team',
controller: 'calendarCtrl',
templateUrl: 'app/modules/calendar/calendarView.html',
})
To make my navigation work I also need access to the :category/:competition/:team-params in my pageCtrl. Can I configure this using the same way? Something like:
$stateProvider
.state("page", {
abstract: true,
controller: 'pageCtrl',
// params: :category/:competition/:team
})
Edit: Using $stateParams in the calendarCtrl works fine. I just can't figure out how I can make sure my pageCtrl also can get read the url.
Since you're using ui.router, inject $stateParams in your controller(s) and then you can access those values like so:
controller.js
function($stateParams){
$stateParams.category
$stateParams.competition
$stateParams.team
My suggestion would be - use more views - the UI-Router built feature.
Multiple Named Views
There is a working plunker
Let's have the 'Parent' state which has this template:
This blue is the parent template. Orange are child views
<!-- HERE is one named view target -->
<div ui-view="title">This is a title filled by child having access to param</div>
...
<!-- HERE is other view target un-named -->
<div ui-view></div>
And its state is very simple. The interesting is the child state, which is taking care about both views:
.state('parent', {
abstract: true,
url: "/parent",
templateUrl: 'tpl.parent.html',
})
.state('parent.child', {
url: "/child/:id",
views : {
'': {
templateUrl: 'tpl.child.html',
},
'title': {
templateUrl: 'tpl.title.html',
controller: 'TitleCtrl',
},
}
})
So, we do have a target for "some other view" title or side bar. Check it here
And we can even place some default implementation there inside of our "non-abstract" parent state.
There is extended plunker with non abstract parent state definition:
.state('parent', {
url: "/parent",
views : {
'': {
templateUrl: 'tpl.parent.html',
},
'title#parent': {
template: 'the parent own TITLE',
},
}
})
Check it here
There is a way, how to grant access to latest/up-to-date $stateParams - including current state and its child(ren) as well. (working example here)
It is surprisingly easy:
.run(['$rootScope', '$state', '$stateParams',
function ($rootScope, $state, $stateParams) {
$rootScope.$state = $state;
$rootScope.$stateParams = $stateParams;
}])
And that's it. (check similar answer and some discussion here)
With this approach, we will even in parent $scopes have updated reference to the latest $stateParams. While in our own, we will still receive just our own part
.controller('ParentCtrl', ['$scope', '$stateParams', function ($scope, $stateParams) {
$scope.currentStateParams = $stateParams;
}])
The above is valid for states like these:
.state('parent', {
url: "/parent?area",
templateUrl: 'tpl.html',
controller: 'ParentCtrl',
})
.state('parent.child', {
url: "/child/:id",
templateUrl: 'tpl.html',
controller: 'ChildCtrl',
})
Working example to play here.
But I still would say, that this is a bit ... against the UI-Router. I would prefer this answer. Because in that case, each view (while injected into some parent area) is really aware about $stateParams, which belongs to that state. What we are doing here is introduction of some observer pattern (we should watch changes if we want to react in parent) and that would later bring more issues then profit

How correct change route controller?

I have simple table page (with controller) and init method like ng-controller="messageGridCtrl" ng-init="init()" and create page with different controller.
Create page has back link like Back to list, when I click route changed and init method invoked, but request don't work (don't recieve to server).
If I just reload (via f5) all works fine.
I'm new to angularjs.
From the angular-route-segment documentation,
$routeSegmentProvider.
when('/section1', 's1.home').
when('/section1/prefs', 's1.prefs').
when('/section1/:id', 's1.itemInfo.overview').
when('/section1/:id/edit', 's1.itemInfo.edit').
when('/section2', 's2').
segment('s1', {
templateUrl: 'templates/section1.html',
controller: MainCtrl}).
within().
segment('home', {
templateUrl: 'templates/section1/home.html'}).
segment('itemInfo', {
templateUrl: 'templates/section1/item.html',
controller: Section1ItemCtrl,
dependencies: ['id']}).
within().
segment('overview', {
templateUrl: 'templates/section1/item/overview.html'}).
segment('edit', {
templateUrl: 'templates/section1/item/edit.html'}).
up().
segment('prefs', {
templateUrl: 'templates/section1/prefs.html'}).
up().
segment('s2', {
templateUrl: 'templates/section2.html',
controller: MainCtrl});
It might help you
http://scotch.io/tutorials/javascript/angularjs-multi-step-form-using-ui-router

With angular.js using ui-router, how to only reload one view?

I have a fairly simple todo app using angular.js for which I am using the ui-router library. I looked through the ui-router example on github (https://github.com/angular-ui/ui-router/tree/master/sample) but was unable to figure out what I am doing wrong. In my app I have a sidebar navigation view (with the list of things todo) and a content view (which displays the todo item's details when clicked). The problem I have is that when I navigate to /todo/exampleItem the content view updates and the navigation panel is reloaded as well. This doesn't effect the functionality of the app but I would like to avoid the navigation panel flickering each time you click on an item.
Here is my code to handle the state changes:
app.config(function ($stateProvider) {
$stateProvider
.state('todo', {
url: "/todo",
views: {
"navPanel": {
templateUrl: "./navPanel.html",
controller: 'PanelController'
}
}
})
.state('todo/:item', {
url: "/todo/:item",
views: {
"PanelView": {
templateUrl: "./navPanel.html",
controller: 'PanelController'
},
"ContentView": {
templateUrl: "./content.html",
controller: 'ContentController'
}
}
})
});
In my index.html my views are set up as follows:
<div class="column" data-ui-view="PanelView"></div>
<div class="column" data-ui-view="ContentView"></div>
Is there some way I can stop the navPanel view from being reloaded each time a new item is clicked?
Based on the voted answer of that question angularjs ui-router - how to build master state which is global across app
app.config(['$stateProvider', function ($stateProvider) {
$stateProvider
.state('todo', {
abstract: true,
views: {
"navPanel": {
templateUrl: "./navPanel.html",
controller: 'PanelController'
}
}
})
.state('todo/:item', {
url: "/todo/:item",
views: {
"ContentView#": {
templateUrl: "./content.html",
controller: 'ContentController'
}
}
})
}]);

Categories