Using binding with UI Router - angularjs

I am working with ui-router and have several states defined. On one of my views I have a form where a user can add a 'team' to the view. I have a button for each team to view additional details on that team. What I am trying to do is set it up so that when I click on that button the team view comes up with the URL like /#/teams/yankees for example.
I may just not be looking in the right places or know the exact term for this, but I have not been able to figure it out so far.
Below is a snippet of what I currently have in my app.js for this portion.
app.config(
['$stateProvider','$urlRouterProvider',
function($stateProvider, $urlRouterProvider){
$urlRouterProvider.otherwise('/');
.state('teams', {
url: '/teams',
templateUrl: './templates/main/teams.html',
controller: 'teamsCtrl'
})
.state('teams/{{ team.title }}', {
url: '/teams/{{ team.title }}',
templateUrl: './templates/main/team.html',
controller: 'topicCtrl'
})
Whenever I click on the button now to go to /#/teams/yankees I end up being routed by $urlRouterProvider.otherwise('/'); Can someone point me in the right direction?

It would be helpful to know what your links look like... are you using ui-sref? Typically url attributes look more like this like this:
.state('teams/{{ team.title }}', {
url: '/teams/:title',
templateUrl: './templates/main/team.html',
controller: 'topicCtrl'
})
rather than the {{}}

Related

angularJs navigation's from ng-route to ui-router

I am new to AngularJS, and I am a little confused of how I can use angularjs ui-router in the following scenario:
It consists of two sections. The first section is the Homepage with its login and sign up views, and the second section is the Dashboard (after a successful login).
When I logged in success need to navigate from login form to "Home page".
When I tapped a registration button I need to navigate to "Registration page" from login page
Similarly I also need a "forgot password" screen
My current router is below. How can I do this functionality? (Please help with some HTML code and related controllers)
app.js:
'use strict';
//Define Routing for app
angular.module('myApp', []).config(['$routeProvider', '$locationProvider',
function($routeProvider,$locationProvider) {
$routeProvider
.when('/login', {
templateUrl: 'login.html',
controller: 'LoginController'
})
.when('/register', {
templateUrl: 'register.html',
controller: 'RegisterController'
})
.when('/forgotPassword', {
templateUrl: 'forgotpassword.html',
controller: 'forgotController'
})
.when('/home', {
templateUrl: 'views/dashBoard.html',
controller: 'dashBordController'
})
.otherwise({
redirectTo: '/login'
});
}]);
});
Firstly, nobody will design a website with your requirements / functionalities for you. stackoverflow is for specific problems, your questions is too broad, more about it - How to Ask. But to help you with a conversion from ngRoute to ui.router I can describe what the syntax should look like so you can adopt it for your website.
Converting to ui.router
Your config doesn't change that much. you need to replace .when with .state, use the right providers, and have the right syntax. Here is an example with just few states:
app.config(config);
/* your preferred way of injecting */
config.$inject = ['$stateProvider', '$urlRouterProvider'];
function config($stateProvider, $urlRouterProvider) {
$stateProvider.
state("HomepageState", {
url: "/home",
templateUrl: 'views/dashBoard.html',
controller: 'dashBordController'
}).
state("RegisterState", {
url: "/register",
templateUrl: 'register.html',
controller: 'RegisterController'
})
/*
more can be added here...
*/
$urlRouterProvider.otherwise('/login');
}
Navigation
You should be using states for navigation at all times. So replace href="url" with ui-sref="state". Here are some examples of anchor links:
<a ui-sref="HomepageState">Home page</a>
<a ui-sref="RegisterState">Register</a>
Don't forget to replace your ng-view with ui-view. (For older browser support it's better to have <div ui-view></div> instead of <ui-view></ui-view>)
Redirection
After filling in a login form, the user will press something like:
<button ng-click="login()">Sign in</button>
which will call a function login() that will validate / verify if the user can be logged in. (You can also have <form ng-submit="login()"> with <button type="submit">...) Then, if everything is fine and the user got his session / cookie, you can have a redirection to another page with:
$state.go("HomepageState");
(Don't forget to inject $state into your controller)
Advanced navigations
In the future if you have user profiles that are listed by their index. Your routing can be improved with $stateParams. Their job is to check any additional parameters in the URL. For example: a URL: /profile/721 can have a state with url:"/profile/:id". Then you can extract that id with $stateParams.id and use it in your controllers. And your redirection would look like:
$state.go("ProfileState", { "id": 721});

Default nested ui-views in ui-router

I'm having trouble with a simple ui-router sample I have set up. I have a company page, whose default sub-state should show CompanyProfile, but it defaults to nothing until I click profile. Once I clicked employees, I have to click profile twice to get it to show again. Ideally I want ui-sref="company()" and ui-sref="company.profile()" to display the same screens. It seems like I'm missing something small..
Here's the plnkr:
http://plnkr.co/edit/A3LHGqQIuRlK1QdjuzrP?p=preview
HTML:
<a ui-sref="company()">company</a>
| <a ui-sref="company.profile()">profile</a>
| <a ui-sref="company.employees()">employees</a>
JS:
$stateProvider
.state('company', {
url: '/',
templateUrl: 'company.html',
controller: 'CompanyCtrl as CompanyCtrl'
})
.state('company.profile', {
url: '',
templateUrl: 'profile.html',
controller: 'CompanyProfileCtrl as CompanyProfileCtrl'
})
.state('company.employees', {
url: '/employees',
templateUrl: 'employees.html',
controller: 'CompanyEmployeesCtrl as CompanyEmployeesCtrl'
});
btw, I'm writing everything as components and decided to define the routes in each component, so you'll find the 3 state definitions in the 3 controllers. I'm not entirely sure this is the best approach or not yet.
The default state is entirely dependent on how you call $urlRouterProvider.otherwise(), passing it a url transitions the application to the particular url, wherein ui-router detects and looks for the very first state it sees.
In your main.js configuration, defines the / url as the default url for the application, which is technically the company state's url and is the very first state in the chain of parent states and children states, making it the default state. This in fact, is also the resulting url for the company.profile state that you wanted your application to default to.
To solve this problem, depends on the use cases for your application.
Use case: If your application defines the company state as a non-navigational state, then setting it to an abstract state solves the problem.
DEMO
CompanyCtrl.js
$stateProvider
.state('company', {
abstract: true,
url: '/',
templateUrl: 'company.html',
controller: 'CompanyCtrl as CompanyCtrl'
});
Use case: If the company state is nagivational, then simply remove the url definition in the company state and change the url defintion for the company.profile state to '/'. The only caveat for this solution would be the loss of the href attribute to be applied for for any anchor tags defined with the ui-sref="company" state which also implies the application of the text cursor. To mitigate this problem you might as well define all anchor tags with ui-sref attribute with a pointer cursor.
DEMO
CompanyCtrl.js
$stateProvider
.state('company', {
templateUrl: 'company.html',
controller: 'CompanyCtrl as CompanyCtrl'
});
CompanyProfileCtrl.js
$stateProvider
.state('company.profile', {
url: '/',
templateUrl: 'profile.html',
controller: 'CompanyProfileCtrl as CompanyProfileCtrl'
})
style.css
a[ui-sref] {
cursor: pointer;
}
UPDATE:
Use Case: The same with use case #2 but making the company state an abstract state.
DEMO
CompanyCtrl.js
$stateProvider
.state('company', {
abstract: true,
templateUrl: 'company.html',
controller: 'CompanyCtrl as CompanyCtrl'
});

Excluding path in url using AngularJS

My angular application has multiple pages which users can visit and I would like to hide all other urls and only show users the base url. So imagine my base url is: www.example.com and I have other pages like About, Contact Us etc. Currently, when the user clicks on About, the url changes to www.example.com/about. Is it possible for angular not to add the "/about"? Is this possible using angular js? Also, I have been searching for solutions and have experimented with ui-router.js, is it also possible with this module?
If you are using ui-router, then you can define states without specifying urls like
myApp.config(function($stateProvider, $urlRouterProvider) {
//
// For any unmatched url, redirect to /state1
$urlRouterProvider.otherwise("/state1");
//
// Now set up the states
$stateProvider
.state('state1', {
url: "/state1",
templateUrl: "state1.html",
controller: 'Controller3'
})
.state('state2', {
templateUrl: "state2.html",
controller: 'Controller2'
})
.state('state3', {
templateUrl: "state3.html",
controller: 'Controller3'
})
});
So by default the url will be /state1. And you can implement navigation by using ui-sref directive in your template like ui-sref="state2" or using $state service in your controller like $state.go('state2').

AngularJS multiple routes using JSON data ids

We are new to AngularJS and finding one-or-two problems with setting up multiple routes when using ID's from Json Data.
We are trying to replicate AngularJS Tutorial, so we can click each 'View' button to display a more detailed page of the selected 'Warranty Item' same as the tutorial.
We have uploaded our AngularJS problem to Plunker, If anyone can see something we're missing or know a better route to go down please let us know.
App.js State with ResultSet.JobID
.state('home.singleWarranty', {
url: '/singlewarranty/{resultset.JobID}',
templateUrl: 'singlewarranty.html',
controller: 'warrantyListController'
})
There is a working/updated plunker
Because there are these states
.state('home', {
url: '/home',
templateUrl: 'home.html',
controller: 'homeController'
})
.state('home.singleWarranty', {
url: '/singleWarranty/:jobID',
templateUrl: 'singlewarranty.html',
controller: 'warrantyListController'
})
We need to build the url like this
View
Instead of this original
// View
The point is that state 'home.singleWarranty' inherits/extends the url from its parent. So we have to include the parents '/home' as well.
Other solution:
In case we would like to start the url in a child state from the begining, we can do it like this
.state('home.singleWarranty', {
url: '^/singleWarranty/:jobID',
See the ^ at the url begining. Then even this would work:
View
Check the updated plunker here

Back button with nested states in Angular Router

I have an AngularJS application that makes use of the new, state-based ui-router. I have three different views in my application, where one is a top-level views, and the other two are nested ones.
The structure basically is as follows:
/ => Top-level view
/foo => Abstract view, loads a view that contains a ui-view placeholder
/foo/bar => View for the placeholder
/foo/baz => View for the placeholder
The router is set up as following:
app.config(['$urlRouterProvider', '$stateProvider', function ($urlRouterProvider, $stateProvider) {
'use strict';
$urlRouterProvider
.when('/bar', '/foo/bar')
.otherwise('/');
$stateProvider
.state('home', {
url: '/',
views: {
'': {
controller: 'homeController',
templateUrl: '/home/homeLayout.html',
},
'firstHomeView#home': {
templateUrl: '/home/firstHomeView.html'
},
'secondHomeView#home': {
templateUrl: '/homme/secondHomeView.html'
}
}
})
.state('foo', {
abstract: true,
templateUrl: '/foo/fooLayout.html',
controller: 'fooController'
})
.state('foo.bar', {
url: '/foo/bar',
templateUrl: '/foo/barView.html',
controller: 'barController'
})
.state('foo.baz', {
url: '/foo/baz',
templateUrl: '/foo/bazView.html',
controller: 'bazController'
});
The problem is, that basically everything works as expected when you click around or manually type in urls, but that it does not work when using the back / forward buttons of the browser.
E.g., is you go to /foo, you are taken to /foo/bar, as expected. When you then click on a link to go to /foo/baz, everything is fine. Then click a link that takes you to /, and everything is still fine.
If you now hit the back button, you are taken back to /foo/baz (which is correct), but only the /foo/fooLayout.html view is rendered, not its sub-view /foo/bazView.html. The strange thing is now that if you hit the back button again, you are taken to /foo/bar and it renders correctly, including its subview! It seems as if nested views weren't recognized when using the back button, at least, if you enter an abstract view at the same time.
$locationProvider.html5Mode is not enabled, but enabling it doesn't make any difference.
I am using AngularJS 1.0.5 and ui-router 0.0.1-2013-03-20.
Any ideas what might cause this issue, and how I might solve it?
I found the error: In the view fooLayout.html I was using ng-view instead of ui-view. Once I changed that, everything was fine :-)

Resources