route to specified number of views in angularjs - angularjs

I am in the process of building a mobile web app with AngularJS. The app will allow the user to record the salary and other figures for employees.
On the first page the user will select the number of employees to be filled for instance 3. When the user clicks next, it will go to employee 1 then next to employee 2 and so on.
The problem is i am having these views do not exist. I will create an augular directive which will contain the elements to be captured for the employee. But then how to route to these views. It should allow to go back as well to edit for any employee.
Any advise is welcome.
Thanks,
Ashley

You can have one state with the form and another parameterised state with the employee ID.
$stateProvider .state('contacts.detail',
{
url: "/contacts/:contactId",
templateUrl: 'contacts.detail.html',
controller: function ($stateParams) {
// If we got here from a url of /contacts/42
expect($stateParams).toBe({contactId: "42"});
}
})
From one employee editing state you can navigate to the next employee editing state.
More info/examples: https://github.com/angular-ui/ui-router/wiki/URL-Routing

Related

Where to store the current state data using angular js?

This issue is happening here.
Plunker link -> https://run.plnkr.co/NMW85SbYq76ujSjV/
I need to store the current state data somewhere apart from local storage using angular js. I have a list of models(cards) in one angular page. And there are two tabs in each card. First tab is having only simple text but second tab is having one button. So when a user clicks on the button (which is present in the second tab) then it redirects to new state where we are showing the description of the current model.
Here one problem is there. When user is on first state (where all of the models are visible) then this user is free to select any tab from any model. So suppose, we have 10 models and user select tab 2 for model 2, 4, 5, and 9. So here the view is like model 1, 3, 6, 7, 8 and 10 will be showing the tab 1 content and rest of the models will be showing the tab 2 content. Now when he/she clicks on the button present in second tab(of any model) then it redirects to description of model state. And here is button to go back to previous state. When he/she clicks on this button then it redirects to models state but the it's showing tab 1 content in all of the models instead of previous selected tabs accordingly.
So how can i handle this situation. I want to show previous state when a user comes back fro description state to models state.
Please help me guys. Please click on the above link to get the implemented plunker sample. Any lead would be appreciated.
Thanks :)
You have to create a service and move the "flag" variable to the JSON.
I have modified your plunker. Please check.
https://plnkr.co/edit/5k8hXbCIid4NonSL4Y9k?p=preview
var getData = {};
getData.get = $http.get('template.json')
.then(function(response) {
console.log(response);
return response.data;
})
return getData;
});
myRouterApp.component('myModels', {
templateUrl: 'models.html',
controller: ['$scope', '$http', '$state','getModelSvc', function TrialCtrl($scope, $http, $state,getModelSvc) {
$scope.models = [];
console.log(getModelSvc);
getModelSvc.get.then(function(data) {
$scope.models = data.models;
console.log($scope.models);
})

Angular UI-Router Best Practices: Share Data Between named views

I'm migrating from angular-route to ui-router and Im trying to figure out what is the best option for build the following scenario:
I have a generic panel wich is composed of two nested elements showed at the same time: A FORM(rendered on the left) and a simple LIST (rendered on the right).
The form is used to edit or even create a new item for the list (this manipulation is made throught a service makes ajax calls)
The list shows all items and I can select one of them and click on "edit", after that the item goes to the form and I'll be able to manipulate/update it.
Here is my code:
.state('mt.demos', {
abstract: true,
url: '/demos',
views : {
'container#' : {
templateUrl: '....demos.html'
}
}
})
.state('mt.panel', {
url: '',
views: {
'form#mt.demos': {
templateUrl: '...form.html',
controller : 'formController',
controllerAs : 'vm',
},
'list#mt.demos': {
templateUrl: '...list.html',
controller : 'listController',
controllerAs : 'vm',
}
}
})
So far I ended up with those 2 options:
Create a service for the shared data (this seems to be the most acceptable answer due to its Singleton behavior -- but look the NOTE 1 at the end of this post.
Create a parent controller so each nested state can access parent properts like the list or the item to be edited. So when I click on "edit item" the listController updates the parent's scope and the formController will be changed with this data.
NOTE 1: Of course to retrieve the list and to update items I already use one service called demoService. This service is used for ajax requests only. So If the best decision is the options 1 showed above, I belive that I should create a new service with a new proposal, right? Or it isnt bad to store some local variable in this same service.
This new service will have the list and the item itself, so when I click on edit I will update the service "item" property?
I think you already have an answer of using a service to store your data.
About a new service with new proposal, while I'm not entirely sure what a 'proposal' means, I'm assuming you are referring to a different list with different fields with your current one?
In that case that would depends on how reusable your code is. If your forms are similar enough, or you can generalize it, then it might be fine to share the same service so you don't have to rewrite the functions. The lists and selected items can be stored as different variables in the service.
Or, you can also store them in different service, and write their common functions in another service.

Resolve on parent state doesn't run on each child state change

I am building an AngularJS app (using router-ui) that uses a tab style navigation. The users page, for example, will have the following tabs:
Listing (will always be the main tab and list all users. Upon selecting a user on this tab, the rest will be come active
Account Details
Contact Details
Notes
etc
Now, I am using a service called entityIdPersistenceService to remember the ID of the user selected on the listing tab. In my routes, I am doing something like the below to notify the child tabs of the selected userId (so they can grab the necessary data), however it seems like alot of repetitive code. Is there a better way to provide my selected id to all other tabs?
resolve: {
entityId: function(entityIdPersistenceService) {
return entityIdPersistenceService.getId();
}
}
It seems like alot of repetitive code. I added it to the parent state, however it looks like the code only runs once on the parent state, and not on every child state change.
Are there any better ways of doing something? Ideally id like to put this on the parent state and have it run at each route change.n
All pages related to a user should have UserId somewhere in the url and in route parameters:
.state('user.accountDetails', {
url: "/users/{userId}/account",
templateUrl: "..."
})
.state('user.contactDetails', {
url: "/users/{userId}/contact",
templateUrl: "..."
})
In this way the UserId will be stored in url instead of the service and every child controller will be able to get it via $stateParams.userId

How does ionic history work and when is a non-root stack created?

I'm using ionic v1.0.0 and do not understand the way parallel history managed by $ionicHistory works.
Especially on Android devices, when using the (formerly hardware-)back button, my Angular app sometimes behaves strange and I'd like to understand why. (example: navigating back opens a view closed by $ionicGoBack() long time ago)
For me it seems like some of the ui-router navigations create new history stacks and others put the history items in the root history, even when going from state to sub-state should append to the history where state is recorded IMO.
Questions
Can anybody explain in which cases ui-sref or $state.go(...) append history items to a newly created stack?
When are they appended to root?
Are modals treated in a special way?
Sorry for not being more specific, but the app is rather complicated and I don't know how to isolate the problems in a single plunkr. Maybe I missed a piece of good documentation...
I'll try to answer this question even if you might not find all the info you're asking.
Lot of people - included myself - seem to struggle to understand how the navigation system and the history works.
I've answered a question earlier trying to explain why things don't work as expected.
It seems the navigation keeps track of each view the user has visited using a collection.
Actually there are 2 collections in the $ionicHistory object.
The first one $ionicHistory.viewHistory().views seems to keep track of each visited view in the current stack while the other $ionicHistory.viewHistory().histories keeps track of all the histories for the whole app.
You might have different types of history for tabs, sidemenus or regular views.
You can see how parallel independent histories work in this codepen.
There are 2 different histories there. One is for the home tab and the second is for the about tab.
Navigating through the sub-items in each tab and going back to the previous tab you'll notice that the navigation system has remember the previous state.
I've prepared another plunker here where you can see how the navigation works with some details displayed in the page.
The collection of views $ionicHistory.viewHistory().views is updated each time the user visits a new page (the current view in the collection is wrapped in square brackets).
If the view has been added to the collection it won't (it shouldn't) be added again.
You can change the behaviour clearing the history ($ionicHistory.clearHistory()) or setting the root for the current history:
$ionicHistory.nextViewOptions({
historyRoot: true
});
In the Invoice page of my plunker there's a green button (Other Root View). When pressed I set the new history root and change state:
$ionicHistory.nextViewOptions({
historyRoot: true
});
$state.go('otherviewroot');
Things work as expected and in fact now I don't have a back view and my stack contains only the current view.
Things get messed up when you try the sequence:
Home - Contacts - Invoices - Home (button in the header).
Now it's seems Ionic has lost control of the sequence and keeps on adding views to the collection.
Pressing the home button should clear the back button, since we are on the root for the current history, but it doesn't happen.
Using the same pattern over and over increases the size of the collection indefinitely.
I guess this is not the right behaviour and a fix is needed.
Going back to your question.
The back button in Android works ... meaning the it follows the same pattern.
Modals luckily are not treated as regular views and don't affect the collection.
As additional information to the previous post.
A history stack is always linked to an "ion-nav-view" template. So the root history stack is created for the first "ion-nav-view" item.
If you plan on using different history stacks I would advise to always link the ion-nav-view to a view name:
<ion-nav-view name="default"></ion-nav-view> instead of <ion-nav-view></ion-nav-view>
In this CodePen you have a RootStack for the tab pages and the other pages (named "tabs", "other", "other1") and then inside the tab pages you have one substack for each tab.
The tab pages and other pages run inside the Root ion-nav-view. During my tests I needed to assign a name to the root ion-nav-view and then reference this view name in controller. Otherwise the stack was always recreated when switching between the main pages (Other => Tabs => Other => ..)
Html for Root Stack:
<ion-nav-view name="default"></ion-nav-view>
Controller:
.state('other', {
url: "/other",
views: {
'default': {
templateUrl: "templates/other.html",
}
},
.state('tabs', {
url: "/tab",
abstract: true,
views: {
'default': {
templateUrl: "templates/tabs.html",
}
}
})
Inside the tabs template I assigned a new ion-nav-view for the different tab stacks (as it is done in the default ionic tabs template)
For example for the home-tab (and home stack) the Html looks like this (pages home, facts):
<ion-nav-view name="home-tab"></ion-nav-view>
Controller:
.state('tabs.home', {
url: "/home",
views: {
'home-tab': {
templateUrl: "templates/home.html",
},
}
})
.state('tabs.facts', {
url: "/facts",
views: {
'home-tab': {
templateUrl: "templates/facts.html",
},
}
})
I also submitted a bug report for the codepen above. It is wrongly switching back across histories.
https://github.com/driftyco/ionic/issues/4086
I'm not sure of my fix though.
Maybe the history feature needs to be redesigned more globally to address issues ..

AngularJS and UI-Router multi-level breadcrumbs element

I'm using AngularJS and UI-Router to make a little e-commerce product gallery. It should display a grid of images representing categories of products. When the user selects a category, the grid shall display the child categories of that one, and so on, until the user reaches a level where there are only products. Clicking in a product should display its details. Im using 2 states in UI-Router, one for the gallery and one for the details.
app.config(function($stateProvider){
$stateProvider
// Gallery State
.state('gallery', {
url: '/products/:category',
templateUrl: 'views/gallery.html',
controller: 'galleryCtrl'
})
// Details State
.state('details', {
url: '/details/:id',
templateUrl: 'views/details.html',
controller: 'detailsCtrl'
});
});
In the 'gallery' state, the controller uses the :category parameter to get from the database all subcategories or products of that category to display in the grid. The 'details' state's controller uses an analog strategy to get the product's information with the :id parameter.
Now I want to make a breadcrumb element that shows the 'path' the user went through the gallery. For example, if the user selects the "Computers" category, then the "Notebooks" category and then "Foo Notebook", the breadcrumb should display:
Computers > Notebooks > Foo Notebook
I've found solutions that get the state hierarchy from UI-Router to create the breadcrumb. The problem is, with only the 2 states I created, the breadcrumb wouldn't show all categories, just the last selected one. I don't want to create a state for each category because the number and hierarchy of categories can change. Is there any way to accomplish this?
If you're really interested in documenting the way a user got somewhere: One way to go about this would be to create a service and push each state change to a data store in the service and replicated in a $cookieStore -- you can use the state change events for this.
Generally, though, whenever I've done breadcrumbs / hierarchies in the past - there is a definitive way to get to a location. Your example illustrates that; a specific notebook is under a general list category which is in turn under a parent category. So you can infer all parents when you get to a given item page. Not sure which solution best meets your needs.

Resources