I'm developing an app where it uses the information of the first page so that, that information is used as the input for the second page. To pass the information I'm using the $stateParams but still, the second page didn't display the output.
html page 1:
<ion-list>
<ion-item ng-model="carBrand" ng-repeat="name in carSelect" ng-click="selectItem(carBrand)">
{{name.name}}
</ion-item>
</ion-list>
html page 2:
<ion-checkbox ng-model="cartype" ng-repeat="brandType in carBrand.types">
<div align="center"><span>{{brandType}}</span></div>
</ion-checkbox><br><br>
controller:
carService.controller('carBrand',['$scope','carRepository','$rootScope','$state','$stateParams',function($scope,carRepository,$rootScope,$state,$stateParams){
$scope.newCarList=[];
$rootScope.carSelect=carRepository.data;
$scope.selectItem=$stateParams.name;
$scope.selectItem=function(key){
$scope.newCarList.push(key);
$state.go('app.CarDetails',{value:$scope.name});
}
app.js
var carService = angular.module('CarWash',['ionic']).config(function($stateProvider, $urlRouterProvider) {
$stateProvider
.state('app.Cartype',{
url:'/Cartype',
views:{
'menuContent':{
templateUrl:'templates/Cartype.html',
controller:'carBrand'
}
}
})
//carEdit.html
.state('app.carEdit',{
url:'/carEdit',
views:{
'menuContent':{
templateUrl:'templates/carEdit.html'
}
}
})
It looks like you're using UIRouter as well?
There are 2 glaring issues I see right away.
you're telling UIRouter to go to a state 'app.CarDetails' which I don't see defined in your $state config
you haven't declared any params to use in your states.
When you want to drive a UI state with parameters, you need to either define the params in the URL or define a params object on the state. Let's assume that you wanted to go to 'app.CarEdit' when you click the item. Your state would look like this:
URL driven parameters:
.state('app.CarEdit', {
url: '/edit/{type}',
....
})
OR
hash-driven parameters:
.state('app.CarEdit', {
url: 'carEdit',
params: { type: undefined }
})
In either case when you call $state.go you need to pass the params back with type defined:
$state.go('app.CarEdit', { type: $scope.selectedType })
Something like that.
Related
I am building a application which has different modules. and two modules can have same pages. So based on url i am making the appropriate ajax call to load data. So I am tring to setup my states in below way:
$stateProvider.state('login', {
url: '/login',
templateUrl: 'login.html',
controller: 'LoginController as LoginController'
}).state('logout', {
url: '/logout',
templateUrl: '',
controller: 'LogoutController as LogoutController'
}).state('module', {
url: '/:module',
params: {
module: DataService.getCurrentModule()
}
}).state('module.cover', {
url: '/cover',
templateUrl: 'cover.html',
params: {
module: 'leads'
}
}).state('module.leads', {
url: '/leads',
templateUrl: 'leads.html',
controller: 'LeadsController as ctrl',
abstract: true
})
Given that at the time of login I will fetch all modules and save it in DataService, which is happening. Then after login two things will be done. One navigation urls which i have formatted in below way:
<a href={'#/'+ module.code +"/" + (menu.type|| menu)}>
<i className={classes}></i> <span >{menu.name || menu }</span>
</a>
which is setting the correct url, and second in app.js in "run" I am checking if login is done them I am doing :
$location.path(DataService.getCurrentModule() + "/" + (home.type || home) );
which is also happening, but issue is desired controller and html page is not being loaded. Am I missing something here. Or should I have done things little differently?
Thanks for help in advance.
Avoid href when working with ui.router. To navigate to the required states use:
In HTML: ui-sref="myStateName({param1: 1, param2: 2})"
In Javascript inject the service $state and do: $state.go('myStateName', {param1: 1, param2: 2});
In your case, lets assume that there are 2 modules in an array in the $scope:
$scope.myModules = [{code: 'modA'},{code: 'modB'}];
Now in the HTML, to go to the module.cover state you would do:
<a ui-sref="module.cover({module: myModules[0].code})">My Link</a>
If you want to do it for all modules, put it inside an ng-repeat:
<a ng-repeat="mod in modules" ui-sref="module.cover({module: mod.code})">My Link</a>
Also, for state configuration, consider:
ALL STATES NEED A TEMPLATE: even if they are abstract states, they require a template to work properly. If the parent state doesn't have a template, not even one of its childs is gonna show. In this case, the state module doesn't have a template, so it will never work. define a template for it as simple as template: '<div ui-view></div>'
When you define a parameter in the URL, there's no need to define it again in with a params property. That is used only when you need parameters that you don't want to show in the URL
I am using angular ui-router to retrieve a page, but on the documentation, it only shows how to pass in parameters in the url, not the template url.
Is there anyway where it can be passed in the templateUrl?
Below is my code
<div ui-view></div>
<!-- We'll also add some navigation: -->
<a ui-sref="contacts({contactId: 1})">State 1</a>
And the angular config:
myApp.config(function($stateProvider) {
$stateProvider
.state('contacts', {
url: "/states?myParam={contactId}",
templateUrl: "states1.html"
});
});
templateUrl can be a function that takes stateParams parameter:
.state('contacts', {
url: "/states?myParam={contactId}",
templateUrl: function(stateParams) {
return "states" + stateParams.contactId + ".html";
}
})
Why would you want it?
The only reason I can think about is that you want to customize the template on the server-side based on the passed arguments. Which goes against the idea of templates :)
Templates should be generic enough.
I have a AngularJs controller in Ionic Framework.
.controller('LocationDetailCtrl', ['$scope','$cordovaGeolocation','$cordovaCamera', '$cordovaFile','$stateParams','Location', LocationDetailCtrl]);
function LocationDetailCtrl ($scope, $cordovaGeolocation, $cordovaCamera, $cordovaFile, $stateParams, Location) {
$scope.locationRow = {};
$scope.test = "";
$scope.images = [];
Location.getById($stateParams.locationId).then(function(result){
//alert("I'm in");
$scope.locationRow = result;
});
}
I have code in view somewhere that does this:
<ion-item class="item-remove-animate item-icon-right" ng-repeat="location in locations" type="item-text-wrap" href="#/locations/{{location.id}}/all">
<h2>{{ location.aplicant_name}}</h2>
<p>{{ location.form_type }}</p>
<i class="icon ion-chevron-right icon-accessory"></i>
<ion-option-button class="button-assertive" ng-click="remove(location)" translate>Delete</ion-option-button>
</ion-item>
In my stateprovider I have this:
.state('location-detail', {
url: '/locations/{locationId}',
abstract: true,
templateUrl: 'templates/location-detail.html',
controller: 'LocationDetailCtrl'
})
.state('location-detail.all', {
url: '/all',
views: {
'loc-detail-view': {
templateUrl: 'templates/location/location-map-all.html'
}
}
})
My problem is, on the first href click I get the values for database, its all alright. But when I go back and press another list time, I would get the same value I got earlier.
Turns out Location.getById() is not being called the second time around.
Never-mind, I found the answer.
Turns out my controller is being cached by default.
I modified the state provider with this code and it now refreshes the view with new model.
.state('location-detail', {
url: '/locations/{locationId}',
cache: false,
abstract: true,
templateUrl: 'templates/location-detail.html',
controller: 'LocationDetailCtrl'
})
The difference here is cache:false.
Cheers!
Ionic views are cached by default, However you can manually set the cache to false in the view, this will make the controller to load again.
read more here, How ever what you have done is also correct, But I personally prefer the method I mentioned here as it will give more control
If you want to keep your page cached for any reason you could wrap all of your function you need to run inside of another funciton and then on the event $ionicView.beforeEnter or afterEnter or enter, you can call that function. Then you can keep the page cached and still have all of your functions run everytime the page is entered. For example in an app i made I did not want to have the homepage uncached, but i need some funcitons to pull
fresh data everytime the page is entered. So I did this:
$scope.$on('$ionicView.beforeEnter', function () {
$scope.doRefresh();
});
That way the page can stay cached but my app still behaves like I want it to. Take a look at some more of the ionicView methods: http://ionicframework.com/docs/api/directive/ionView/
I am building an application that uses ui-router. On my /teams route I have a form where a user can add a team name which then pushes the name to my MongoDB and binds to the view and displays the team name with several options, one of those being a button that links to a page where more specific information can be added for the team. I have the routing working on this and the url appears like /#/teams/oklahoma or /#/teams/washington for example. Here is what my routing looks like:
app.config(
['$stateProvider','$urlRouterProvider',
function($stateProvider, $urlRouterProvider){
$urlRouterProvider.otherwise('/');
.state('teams', {
url: '/teams',
templateUrl: './templates/main/league.html',
controller: 'leagueCtrl'
})
.state('teams/:title', {
url: '/teams/:title',
templateUrl: './templates/main/team.html',
controller: 'teamCtrl'
})
Here is my link to the /teams/:title route:
<a href="#subjects/{{ team.title | lowercase }}">
<button ng-click="viewTeam(team)" class="team-button">View</button>
</a>
Currently I do not have anything in my viewTeam() function. My question is how do I bind to my {{ team.title }} and other related information in the new view with the new URL? I know a factory must be somehow involved and I have tried implementing the solution described at http://onehungrymind.com/angularjs-communicating-between-controllers/ without success. Any additional guidance would be very much appreciated.
The URL should probably contain the team ID. I'm going to assume your 'teams' array is loaded using $http from some backend API.
app.config(
['$stateProvider','$urlRouterProvider',
function($stateProvider, $urlRouterProvider){
$urlRouterProvider.otherwise('/');
.state('teams', {
url: '/teams',
// the `teams` state will wait to load until $http.get() call is completed.
// this resolve declaration will provide the resulting teams array as an injectable 'teams' object.
resolve: { teams: function($http) { return $http.get("/teams.json"); },
templateUrl: './templates/main/league.html',
// This simplified controller injects the 'teams' resolve and simply sticks the list of teams on the scope to ng-repeat etc.
controller: function($scope, teams) { $scope.teams = teams; }
})
// This is a nested state, called `teams.team`. It requires a `teamId` parameter.
// The parameter can be provided by a URL: http://localhost/app#/teams/9237594827
// The parameter can be provided by $state.go: $state.go('teams.team', { teamId: 9237594827 });
// The parameter can be provided by uiSref: <a ui-sref="teams.team({ teamId: repeatedTeam.id })">{{repeatedTeam.title}}</a>
.state('teams.team', {
// `teams.team` state declares a `teamId` state parameter in the URL
url: '/teams/:teamId',
// This resolve function uses $stateParams to locate the correct team from the list.
// `team` will be made available for injection
resolve: {
team: function($stateParams, teams) {
// Find the correct team from the `teams` array, by ID.
return teams.filter(function(team) { return team.id === $stateParams.teamId; })[0];
}
},
templateUrl: './templates/main/team.html',
// Inject the `team` resolve and put it on $scope
controller: function($scope, team) { $scope.team = team; }
})
league.html:
<ul>
<li ng-repeat="team in teams">
<a ui-sref="teams.team({ teamId: team.id })">{{team.title}}</a>
</li>
</ul>
I am using Angular UI Router and seem to be experiencing an odd issue. When I click a link that has a ui-sref directive attached to it, it successfully loads the new view as I would expect, HOWEVER, it does not update the URL bar. I believe this is ocurring because the parent state's url is a dynamic StateParam /:room. How do I get around this issue?
Here is a snippet of my UI Router
// Room
.state({
name: 'room',
url: "/:room",
views: {
"main": {
templateUrl: "views/pages/chat.html",
controller: "RoomCtrl"
},
"login#room": {
templateUrl: "views/partials/_login.html"
},
"navigation#room": {
templateUrl: "views/partials/_navigation.html",
controller: "NavigationCtrl"
}
},
resolve: {
userLocation: function(geolocationFactory) {
return geolocationFactory;
}
}
})
// Share
.state({
name: 'room.share',
url: "/share",
views: {
"share#room": {
templateUrl: "views/partials/_share.html",
controller: "ShareCtrl"
}
}
});
ui-sref
<button id="share-button" ui-sref="room.share">Share</button>
I created a plunker to demonstrate what is happening
So we can navigate among rooms like this:
<a ui-sref="room({room:1})">room 1</a>
<a ui-sref="room({room:2})">room 2</a>
<a ui-sref="room({room:3})">room 3</a>
this will in fact creat the url like this
#/1 // where 1 represents the id of the :room
#/2
#/3
Now, we can navigate to the substate .share without specifying the :room id
<a ui-sref="room.share">room.share</a>
And what will happen? Firstly the place for :room will be empty ... no room is selected.
Secondly - the previously selected room (its :room id) won't be changed. So the resulting URL will depend on the already selected room. If we were in a room 2, the generated url will be:
#//share
but we will be redirected to
#/2/share
becuase there is still $stateParams.room === 2
Finally, we should always pass the complete state signature:
<a ui-sref="room.share({room:1})">room.share({room:1})</a>
<a ui-sref="room.share({room:2})">room.share({room:2})</a>
<a ui-sref="room.share({room:3})">room.share({room:3})</a>
Check that all here (click the top right corner blue icon to open the prview in sepearate window with url)
I had this problem because my parameter names did not match my URL definition.
For example, I had a parameter set like this:
{
page: {...},
results: {...},
sort: {...},
}
...and a URL like this:
url: '/foo?page&results&orderby'
After fixing the mismatch between sort and orderby, the address bar updated as expected.