AngularJS $stateParams when using reloadOnSearch:false - javascript

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
});

Related

Ionic: $state.go() changes URL but not the view

I'm totally new to Ionic and JavaScript and I'm having a few problems when changing views in my project.
I've created the project using the tabs starter, and everything works when moving withing the default tabs and even when adding new ones. At certain parts of the code, I need to move to a tab view so I'm using the $state.go() function and it works fine. However, I've added a new view with its template, controller, and state and I need to load it when clicking a button. So I use $state.go() again, but the URL in the explorer changes but not the view, it stays in the previous one. It doesn't work either when I type the URL in the browser, so maybe the problem is in the state definition, but I'm pretty sure it is ok.
State
.state('tab.file_explorer', {
url: '/file_explorer',
views: {
'tab-file_explorer': {
templateUrl: 'templates/tab-file_explorer.html',
controller: 'file_explorerCtrl'
}
}
})
Controller
It is in the controller of another view where the button is located (the button works fine, I've tested it). The file_explorerCtrl controller is empty at the moment.
.controller('load_csvCtrl', function($scope, $state) {
$scope.loadCsv = function(){
$state.go('tab.file_explorer');
}
}
This redirects to the URL http://localhost:8100/#/tab/file_explorer, with no console output or 404 errors. I've also tried using $location.path() and $window.location.assign() but it also fails to load the template.
I'd appreciate any help.
Can you check if your index.html has <ion-nav-view></ion-nav-view> tag
You're using named views. your <ion-nav-view> should match the name:
<ion-nav-view name="tab-file_explorer"></ion-nav-view>
Check the docs here:
https://github.com/angular-ui/ui-router/wiki/Multiple-Named-Views
Set cache-view="false" in View.
Example:
<ion-view cache-view="false">
<!-- View Content goes here -->
</ion-view>

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
});

ui-router: Reset $state without using $state.go()

First off, I think the overall issue here is that AngularJS still doesn't have a sensible, best practice way of "restarting" the app and all its components. So far, the best practice seems to be setting the path to a "default" view, and then reloading the window. We do this in our /logout state, as seen here:
$stateProvider.state('logout', {
onEnter: function($state, $window, store) {
//Remove any session variables
store.remove('varA');
store.remove('varB');
//"Logout" the user
$state.go('login');
$window.location.reload();
}
})
However, this is a bad user experience. The user can actually see the view change and the components on the page shift before the window reloads. It just seems very buggy overall.
Originally, we did not include $state.go('login'), and did not get the weird experience of seeing the view change before logout. However, when we started using $state handlers like $rootScope.$on('$stateChangeStart', function (event, toState, toParams), we noticed that toState was not being reset after the window reload. So $stateChangeStart would trigger after the reload, and toState would still be set to whatever view the user was on before calling /logout. This isn't a true app reset!
Possible Solution: I think all of this can be solved if there was a way to "reset $state" without using the $state.go() method...something that happens behind the scenes instead.
Simple code change fixed it for me
//"Logout" the user
$state.go('login', null, {notify: false}).then(function() {
$window.location.reload();
});
Source: https://github.com/angular-ui/ui-router/issues/2486#issuecomment-180872463

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

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....
});

AngularJS. How to disable auto-scroll to top of my page

Tell me please, how can I disable auto-upto top of my page?
If I use hash nav:
Goto index
my page doest up to top, but if I use AngularJS:
Html:
<a ng-href="#/index">Goto index</a>
JS:
$routeProvider.
when('/index', {
template:'...',
controller: 'RouteCtrl'
})
my page scrolled to top. How can I disable it?
I find it a bit strange that your plain href doesn't scroll and ng-href scrolls, I thought it was the other way round...
But, to the solution; It's up to the browser to scroll on hash changes, so usually to disable it you need to intercept and preventDefault() the event and then change the location by yourself. When using Angular, you can either define some attribute directive for the <a> element or just define your own a directive.
If you use ng-view, it relies on $anchorScroll service with view updates to simulate the behaviour what the browser would normally do, as Angular already intercepts the event. You can prevent the scroll on view load by providing your own $anchorScroll which does nothing:
angular.module('yourModule', []).value('$anchorScroll', angular.noop);
As indicated in the AngularJS documentation, the proper way to do this is:
angular.module('yourModule',[]).config( ['$anchorScrollProvider',
function($anchorScrollProvider) {
$anchorScrollProvider.disableAutoScrolling();
}]
);
just try
assessmentApp.run(['$anchorScroll', function($anchorScroll) {
$anchorScroll = angular.noop;
}])

Categories

Resources