$state.go() doesn't load controller in ionic application - javascript

Using the following code, when a page with id=0 loads first time there is no problem with controller. But when again the same page loads with same id=0 again, it does not loads controller.
$state.go('tab.dash', {
id: $rootScope.products[CONSTANTS.i].id
}, {
reload: true
});
How does it happen? Please suggest me a solution.

I encountered a similar problem where I needed stats to recalculate every time a tab was visited.
You need to disable view caching. You can do so in the route setup. For example:
.state('tab.stats', {
url: '/stats',
views: {
'tab-stats': {
templateUrl: 'templates/tab-stats.html',
controller: 'StatsCtrl'
}
},
cache: false
})

well, When you cache the view (by default it is true) controller is loaded only at first time and on subsequent navigation it will attach and detach the scope. Cacheing helping with the performance of single page applications. If you dont want to disable the caching then you use the ionic view events like (enter, leave,loaded and so on).
$scope.$on('$ionicView.enter', function () {
// ur stuff in here....
});

Related

SAPUI5 routing reset after browser refresh

I have developed a SAPUI5 master detail app. When I'm clicking on a master item, the corresponding detail page is shown (so far so good). The problem now is, that if I hit refresh (F5) in the browser, the last selected item is loaded (because of the URL parameter).
What I want to achieve is, to display the master list, but no item is selected. Instead a "select an item" page should be shown instead of the item detail page.
I've tried many things such as manipulate the routing, but none of this works. Any ideas on how to achieve this?
By doing that you give up the whole idea of deep-linking which is imho one of the major benefits of the routing. So think twice before doing so.
Anyways you could just reset the hash before initializing the router in your Component like this:
sap.ui.define([
"sap/ui/core/UIComponent",
"sap/ui/core/routing/HashChanger"
], function (UIComponent, HashChanger) {
"use strict";
return UIComponent.extend("sap.ui.demo.nav.Component", {
metadata: {
manifest: "json"
},
init: function () {
// reset the routing hash
HashChanger.getInstance().replaceHash("");
// call the init function of the parent
UIComponent.prototype.init.apply(this, arguments);
// create the views based on the url/hash
this.getRouter().initialize();
}
});
});
BR
Chris

Angular ui-router not loading external content on state change

I have started building a website using Angular, and have started to use ui-router along with ngAnimation for some sick animations! All was going well until I started adding external resources such as Facebook's Page Widget (https://developers.facebook.com/docs/plugins/page-plugin) and Google Maps API for some custom map styles.
The Issue
I have the Facebook widget on the home page, and it loads fine when you first access the URL as can be seen below (Have to block the name of client, totally not just bad design...):
Once I click on another page to load it in (using ui-view to dynamically bring in a view), for example contact view and go back to the home page (where the code is to display the widget), the widget will no longer load but will load the basic header tag that Facebook provide as can be seen below:
This also happens on the contact page when loading in Google Maps API. If I click on the contact page, there will just be a large white area on where the map should be, but if you had to actually refresh the page the map will load.
I am assuming that the issue is that the website is not able to send a request to either Facebook or Google when a view is loaded in, but can only happen when the page is actually refreshed or a new page load.
My Code
Okay so I'll explain the basics of how my application works along with code. I am rather new with Angular so if I have terrible code, please let me know.
Structure
This is a screen shot of my web apps structure. The main template file is index.html, and any view are within the views directory, which are loaded in using ui-router.
Main Angular applications code (app.js)
var app = angular.module('bmApp', ['ngAnimate', 'ui.router', 'ui.bootstrap'])
.config(function($stateProvider, $urlRouterProvider) {
$stateProvider
.state('header', {
templateUrl: './assets/views/template.html',
})
.state('header.home', {
url: '/',
templateUrl: './assets/views/home.html',
controller: "HomeController"
})
.state('header.about', {
url: '/about',
templateUrl: './assets/views/about.html',
controller: "AboutController"
})
.state('header.work', {
url: '/work',
templateUrl: './assets/views/work.html',
controller: "WorkController"
})
.state('header.services', {
url: '/services',
templateUrl: './assets/views/services.html',
controller: "ServicesController"
})
.state('header.contact', {
url: '/contact',
templateUrl: './assets/views/contact.html',
controller: "ContactController"
});
$urlRouterProvider.otherwise('/'); //if no views are matched, just redirect back to home page.
})
I am using nested views to keep the header of the website static (not changing) and then loading in views under the header, with ngAnimate to make it look cool.
In my main template, index.html, I have a simple <div ui-view></div> to load in the view that is requested. I also have the required script to request Facebook's API just after the . My controllers do not actually currently have anything in them. I did have some vanilla JavaScript in some, but do not currently need it anymore. I also tried to wrap the code provided by Facebook in a function, and call it within the controller for the specific view but that just had the same results of having it within the body on the template (index.html) page.
Pulling my hair out at this, can't seem to find a solution. I hope I have explained my issue without missing out on anything. I appreciate any help you could give, would be so awesome.
Edit: I should have probably mentioned that my main template is index.html, I then inject the view in to /views/template.html AND THEN inject it into index.html. Not too sure if this is best practice, but felt like it would work well (I don't think that is the issue).
I will give you only half of an answer, but maybe it will point you to right direction. I also struggled with Google API in SPA application once. I had the same issue - after entering the contact page, a white box appeared instead of map. The solution turned out to be simple - I just needed to force map reload, when I entered contact sheet. This function was attached as onclick event to contact page link:
function reloadGoogleMap() {
if (counter == 0) {
document.getElementById('google-map').src += '';
counter++;
}
}
I used the counter to make sure it happens only once - you won't need it probably. With Angular, you might need to make sure the reload happens after element is rendered. Maybe a simple directive would work, however I didn't test that:
angular.module('your_directives_module')
.directive('mapLoaded', [mapLoadedDirective]);
function mapLoadedDirective() {
return {
restrict: 'A',
link: function (scope, elem, attrs) {
elem.on('load', function (event) {
// Force reload
elem.src += '';
});
}
};
}
It could be used like:
<!-- Div/iframe with google map -->
<div map-loaded></div>
Maybe Facebook API also has some simple way which you could use to force widget reload when the partial view is loaded, however I've never tried to use that with Angular.
Don't you have to wrap it in a $rootScope.$apply function in order to update your view?
$rootScope.$apply(function () {
// some code
});

AngularJS $stateParams when using reloadOnSearch:false

I have a page in my application which uses a search so i have added the "realoadOnSearch:false" which works perfectly
The problem I have is when navigating to the same state with a different stateParam:
when I navigate to #/category/20/ from any other page it works fine... i then have a link on that page to #/category/3 (the parent category for 20) and the URL updates, however the content does not (no console errors)
app.js (main application)
.state('category', {
url: '/category/:categoryId/',
templateUrl: '/Home/Category',
controller: 'categoryCtrl',
reloadOnSearch: false
})
I have tried adding target="_self" to force page reload and it does not work
I have also tried to watch $stateParams for changes and there is nothing
Clicking the link to #/category/3 from #/category/20 (and vice versa) should navigate to the new page and reload the data, where search should NOT reload the page (latter works but not the former)
The URL is prefered to be a ng-href rather than ng-click as it is managed by the root controller
EDIT:
I did not find a direct solution, however i just disabled the reloadOnSearch and my sorting buttons still work so this works for me for now as a solution.
The problem is that reloadOnSearch doesn't do what you think it does; it's actually more like reloadOnStateParams. Setting it to false prevents you from making state changes where only the stateParams change, which is what you're doing here (going from #/category/3 to #/category/20).
You can see this documented on the UI router issues page: https://github.com/angular-ui/ui-router/issues/1079
There's some workarounds in there but none of them are great. You are probably best off using an ng-click that forces a reload manually, something like this:
$state.transitionTo($state.current, $stateParams, {
reload: true,
inherit: false,
notify: true
});

angularjs $anchorScroll sometimes refresh all page

I have an app with angularjs routing, but on some view i want to scroll to some specific div and i use anchorScroll but sometimes (not all times) it refresh all page even i stop event propagation.
Did anyone had this issue?
$scope.redirectTodiv = function(divname,event) {
event.stopPropagation();
event.preventDefault();
$location.hash(divname);
$anchorScroll();
};
Try like this
$scope.redirectTodiv = function(divname,event) {
var id = $location.hash();
$location.hash(divname);
$anchorScroll();
$location.hash(id);
};
The way to ensure navigation with one click is to combine $location.hash() $anchorScroll and setting routeProvider reloadOnSearch property to false i.e.
In your controller code:
$location.hash("editor");
$anchorScroll();
In your route provider:
$routeProvider.when("/masters/voucher", {
templateUrl: "views/card/voucher.html",
reloadOnSearch: false
})
I've two use cases on the same page :
When clicking save, if the response is an error, scroll to the errorDiv that displays the error to the user.
David Kabii's answer did work for me.
However, on the load of the page, in the controller, I want to scroll to a specific area of the page where the user's input is expected. This wouldn't work. I had to use window.setTimeout to workaround this. (there's probably a better way)
window.setTimeout(function(){
$location.hash("anchorForm");
$anchorScroll();
}, 300);

angularjs - refresh when clicked on link with actual url

I use routeProvider to define controlers and templates for my urls.
When I click on the link, which has the same url as is the actual location, nothing happens. I would like the reload() method to be called if a user clicks on such a link even if the location hasn't changed. In other words, if I set the location to the same value, I would like it to behave the same as if I would set it to different value.
Is there a way to configure routeProvider or locationProvider to do it automatically? Or what is the right approach to do this? This is stadard behaviour in round trip applications, but how to do it in angularjs?
I've asked it on google groups as well.
UPDATE:
This question is getting lots of views, so I will try to explain how I solved my problem.
I created a custom directive for linking in my app as Renan Tomal Fernandes suggested in comments.
angular.module('core.directives').directive('diHref', ['$location', '$route',
function($location, $route) {
return function(scope, element, attrs) {
scope.$watch('diHref', function() {
if(attrs.diHref) {
element.attr('href', attrs.diHref);
element.bind('click', function(event) {
scope.$apply(function(){
if($location.path() == attrs.diHref) $route.reload();
});
});
}
});
}
}]);
The directive is then used for all links in my app I want to have this functionality.
<a di-href="/home/">Home</a>
What this directive does is that it sets the href attribute for you based on di-href attribute so angular can handle it like always and you can see the url when you hover over the link. Furthermore when user clicks on it and the link's path is the same as the current path it reloads the route.
Add a / (slash) to the defined url in the route configuration
I met a similar problem today, I have a link in my web page and when I click it, I want the ng-view reload each time, so that I can refresh data from server. But if the url location doesn't change, angular doesn't reload the ng-view.
Finally, i found a solution to this problem. In my web page, I set the link href to:
test
But in the route config, I set:
$routeProvider.when('/test/', {
controller: MyController,
templateUrl:'/static/test.html'
});
The different is the last slash in url. When I click href="#/test" for the first time, angular redirect the url to #/test/, and load ng-view. when i click it second time, because the current url is #/test/, it's not equal to the url in the link (href="#/test") I clicked, so Angular triggers the location change method and reloads the ng-view, in addition Angular redirects the url to #/test/ again. next time i click the url, angular does the same thing again. Which is exactly what I wanted.
Hope this was useful for you.
You can add a _target='_self' on the link to forces the page to reload.
e.g.
{{customer.Name}}
Tested with version 1.0.5 and 1.2.15 on IE and Firefox.
Here's more information from AngularJS site :
Html link rewriting
When you use HTML5 history API mode, you will need different links in different browsers, but all you have to do is specify regular URL links, such as:
link
When a user clicks on this link,
In a legacy browser, the URL changes to /index.html#!/some?foo=bar
In a modern browser, the URL changes to /some?foo=bar
In cases like the following, links are not rewritten; instead, the browser will perform a full page reload to the original link.
Links that contain target element
Example: link
Absolute links that go to a different domain
Example: link
Links starting with '/' that lead to a different base path when base is defined
Example: link
you should use $route.reload() to force the reload.
I don't know if is there a 'automatic' way to do this, but you can use ng-click on these links
For people who are using AngularUI Router. You can use something like this:
<a data-ui-sref="some.state" data-ui-sref-opts="{reload: true}">State</a>
Notice the reload option.
Found the answer here: https://stackoverflow.com/a/29384813/426840
From #Renan Tomal Fernandes answer. following is an example
HTML
<a href="#/something" my-refresh></a>
JS
angular.module("myModule",[]).
directive('myRefresh',function($location,$route){
return function(scope, element, attrs) {
element.bind('click',function(){
if(element[0] && element[0].href && element[0].href === $location.absUrl()){
$route.reload();
}
});
}
});
I think it's a simpler approach.
.directive ('a', function ($route, $location) {
var d = {};
d.restrict = 'E';
d.link = function (scope, elem, attrs) {
// has target
if ('target' in attrs) return;
// doesn't have href
if (!('href' in attrs)) return;
// href is not the current path
var href = elem [0].href;
elem.bind ('click', function () {
if (href !== $location.absUrl ()) return;
$route.reload ();
});
};
return d;
});
Assuming You want to make all basic <a> links (without target attribute) reload on click and You use relative links in the href attribute (e.g. /home instead of http://example.com/home) You don't have to add any special markup to your HTML (comes handy when updating a site with HTML already written).
In my case if the url is same, nothing worked including $route.reload(), $location.path(), $state.transitonTo() etc.
So my approach was Using Dummy Page as follows,
if( oldLocation === newLocation ) {
// nothing worked ------------
// window.location.reload(); it refresh the whole page
// $route.reload();
// $state.go($state.$current, null, { reload: true });
// $state.transitionTo($state.current, $stateParams, {reload:true, inherit: false, notify: false } );
// except this one
$location.path('/dummy');
$location.path($location.path());
$scope.$apply();
}
You need to make '/dummy' module somewhere, the module doesn't do anything, it only change url so that next $location.path() can be
applied. Don't miss $scope.$apply()
I ran into this issue a moment ago, except for it was the home page '/'. I wanted a simple solution with less code. I just took advantage of the .otherwise method in the $routProvider
So in the html link looks like:
Home
since there is no '/home' page specified in the routProvider it will redirect to '/' via the 'otherwise' method. page with this set up:
.otherwise({
redirectTo: '/'
});
Hope it helps someone
I tried Wittaya's solution above using directive approach. Somehow the directive keeps throwing error. I end up with this solution
HTML
Devices
Controller
$scope.stateGo = function (stateName) {
if ($state.$current.name === stateName) {
$state.reload();
} else {
$state.go(stateName);
}
}
Just tried adding this
$(window).on('popstate', function(event) {
//refresh server data
});
and it works fine

Categories

Resources