angular ui.router and linking to dynamic pages - javascript

I am working on a backend rails app that produces and API for a front end ionic app to consume. I have the rails side (mostly) done, and am building the ionic app. I have experience working with angular, but not ionic.
Anyway, my question is I have a resource I'm receiving from the API. It's static, and the only actions available to it are index and show. I receieve the index action fine and can list them, but linking to the show pages results in a blank white screen. I put a couple console.log calls in the angular show controller to see if it's running at all, and it is, but it's not linking to the page. Here is the set up:
app.js
.config(function($stateProvider, $urlRouterProvider) {
$stateProvider
.state('app', {
url: "/app",
abstract: true,
templateUrl: "templates/menu.html",
controller: 'AppCtrl'
})
.state('app.search', {
url: "/search",
views: {
'tab-search': {
templateUrl: "templates/search.html"
}
}
})
.state('app.gyms', {
url: '/gyms',
views: {
'tab-gyms': {
templateUrl: 'templates/gyms.html',
controller: 'GymsIndexCtrl'
}
}
})
.state('app.gymShow', {
url: "/gyms/:gymId",
views: {
'tab-gyms': {
templates: "templates/gym.html",
controller: 'GymsShowCtrl'
}
}
})
$urlRouterProvider.otherwise('/app/search');
})
controllers
angular.module('myApp.controllers', [])
.controller('GymsIndexCtrl', function($scope, $stateParams, Gyms) {
$scope.gyms = Gyms.index(function(response) {
console.log("from gyms");
console.log(response);
});
})
.controller('GymsShowCtrl', function($scope, $stateParams, Gyms) {
$scope.gym = Gyms.query({id: $stateParams.id}, function(response) {
// this is what's running, and it works
console.log("running");
console.log(response);
});
})
gyms.html
<ion-view view-title="Gyms">
<ion-content>
<h1 class="text-center">Gyms</h1>
<hr class="generic">
<div ng-repeat="gym in gyms">
<div class="list card">
<div class="item item-avatar">
<h2 class="pull-left"><b>{{gym.name}}</b></h2>
<p class="pull-lefft">{{gym.description}}</p>
</div>
<div class="item item-image">
<img src="{{gym.images}}" style="min-height: 200px;">
</div>
<!-- where the linking is. I have tried routes like this, and the
ui.router syntax of ui-sref="app.gymShow({gymId: gym.id})"
neither produce and error, but neither work -->
<a class="item item-icon-left assertive" href="#/app/gyms/{{gym.id}}">
<ion-icon name="person"></ion-icon>
{{gym.reviews_count}} reviews
</a>
</div>
</div>
</ion-content>
</ion-view>
In the ionic scaffold example, it uses this
.state('app.playlists', {
url: "/playlists",
views: {
'tab-playlists': {
templateUrl: "templates/playlists.html",
controller: 'PlaylistsCtrl'
}
}
})
.state('app.single', {
url: "/playlists/:playlistId",
views: {
'tab-playlists': {
templateUrl: "templates/playlist.html",
controller: 'PlaylistCtrl'
}
}
})
and I have tried to follow that exactly, but still not luck.
I have 2 questions. The first is how do I link to say show pages from an index action in ionic. And the second would be, can I use $routeProvider in Ionic? I know I should be able to, but I have not seen many resources showing that, so I do not want to cause too much overhead related to that just because I was having problems linking pages.
Any help pointing me in the right direction about either of those questions is very much appreciated.

So this was incredibly dumb on my part. In this section
.state('app.gymShow', {
url: "/gyms/:gymId",
views: {
'tab-gyms': {
templates: "templates/gym.html",
controller: 'GymsShowCtrl'
}
}
})
was supposed to be changed to this
.state('app.gyms', {
url: '/gyms',
views: {
'tab-gyms': {
templateUrl: 'templates/gyms.html',
controller: 'GymsIndexCtrl'
}
}
})
dumb syntax error on my end

Related

ui-view inside another not showing

I have a question regarding Angular UI-Router and its ui-views. I declare three ui-views inside another one, and the only one that shows up is the one with the name "languages". I don't understand why this happens, and if anybody could help that would be great.
index.html:
<div ui-view="languages">
<div ui-view="dashboard"></div>
<div ui-view="partners"></div>
<div ui-view="footer"></div>
</div>
routes.js:
angular.module('TMHM')
.config(routeConfig);
routeConfig.$inject = ['$stateProvider', '$urlRouterProvider'];
function routeConfig ($stateProvider, $urlRouterProvider) {
$stateProvider
.state('home', {
url: '/',
views: {
'languages': {
templateUrl: 'views/languages/languages.html'
},
'dashboard': {
templateUrl: 'views/dashboard/dashboard.html'
},
'partners': {
templateUrl: 'views/partners/partners.html'
},
'footer': {
templateUrl: 'views/footer/footer.html'
}
}
});
$urlRouterProvider.otherwise('/');
};
Here's the Plunker code, although I couldn't get that to work:
https://plnkr.co/edit/z8cFGHKVQNN623QbBUqi
There is updated and working plunker https://plnkr.co/edit/vKOr2yLUfaAfwoGyK0ws?p=preview
I created new routes.html, with this content
<h1>Routes</h1>
<hr />
<div ui-view="languages"></div>
<div ui-view="dashboard"></div>
<div ui-view="partners"></div>
<div ui-view="footer"></div>
And changed index.html to contain
<div ui-view=""></div>
And then state adjustment is:
.state('home', {
url: '/',
views: {
'': {
templateUrl: 'routes.html'
},
'languages#home': {
templateUrl: 'languages.html'
},
'dashboard#home': {
templateUrl: 'dashboard.html'
},
'partners#home': {
templateUrl: 'partners.html'
},
'footer#home': {
templateUrl: 'footer.html'
}
}
});
Also, essential was move the ng-app from <head> to <html> element
<html ng-app="TMHM">
<head >
check it here
More details and examples about named and multi views:
Nested states or views for layout with leftbar in ui-router?
Angular UI Router - Nested States with multiple layouts
I've never seen that done this way before (a routed view in a routed view). That may be because it doesn't work, or I've just never run into it, I don't know. I tend to think of views as being top level, and then includes as being the nested content.
If that's the idea, I've done something very similar to this, but I used ng-include (I currently have this in production in an app serving a lot of users):
<div ng-include="mycontroller.pathToFileIWantToShow"></div>
// alternatively, although hardcoding can be evil...
<div ng-include="path/to/some/file.html"></div>
This allows me to change the content dynamically, use binding etc. etc, and each included template can reference its own controller, or just use the controller that wraps it. It doesn't seem to matter how many I nest.

How to use angular states and nested views for my three panel design?

I am learning angular js and I have start with simple todo app. But I am confused with ui views, states and directives.
I also need the data available in all three states. this is where I am stuck right now, I need to put it in $rootScope which is not good practice. I also want to assign different controllers to all three panels
Here is the full code https://github.com/udayghulaxe/ticitic_todo
What I want is this
This is my app strucutre
I want a list of project in first panel, then list of tasks in second panel,and then tasks detail in third
What I have done so far is this.
$stateProvider
.state('dashboard', {
url: '/dashboard',
abstract: true,
views: {
'': { templateUrl: './partials/main.html'},
'header_toolbar#dashboard': { templateUrl: './views/header_toolbar.html' },
'sidenavleft#dashboard': { templateUrl: './views/sidenav.html' },
'widgets#dashboard': { templateUrl: './views/widgets.html'},
'todo_detail#dashboard': { templateUrl: './views/todo_detail.html' }
}
})
.state('dashboard.listdetail', {
url: '/lists/:list_id/',
templateUrl: './partials/list.detail.html',
controller:'ListController',
resolve: {
list_id: function($stateParams){
return $stateParams.list_id;
}
},
data: {
authorizedRoles: [USER_ROLES.user],
pageTitle: 'Lists'
}
})
.state('dashboard.tododetail', {
url: '/lists/:list_id/:todo_id',
templateUrl: './partials/list.detail.html',
controller:'ListController',
resolve: {
list_id: function($stateParams){
console.log($stateParams);
return $stateParams.list_id;
}
,
todo_id: function($stateParams){
console.log($stateParams);
return $stateParams.todo_id;
}
}
});
<div id="appContainer" md-theme="{{ dynamicTheme }}" ng-init="load()" md-theme-watch>
<!-- Header Toolbar -->
<div ui-view="header_toolbar"></div>
<div layout="row" layout-xs="column" layout-sm="column">
<!-- Sidenav right view -->
<div ui-view="sidenavleft" id="nav_container"></div>
<!-- Main middle container -->
<div flex="100" flex-gt-sm="55" layout="column" id="list_content">
<md-content layout="column" flex class="md-padding">
<div ui-view></div>
</md-content>
</div>
<!-- Todo Detail View -->
<div ui-view="todo_detail" id="todo_detail_view"></div>
</div>
</div>
can someone please help me writing correct structure(ui states) for my app.

URL Changes but the view fails to change

When I view the page in Google Chrome and I click on the goal list that has been generated the URL changes to URL/#/tabs/personalview but the view fails to change.
This is the code in my personalGoals.html file:
<ion-view view-title="PersonalGoals">
<ion-content class="has-footer">
<ion-item ng-repeat="goal in goals" href="#/tabs/personalview">
<span class="goal-lists">{{goal.goaltitle}}</span>
</ion-item>
</ion-content>
</ion-view>
This is the code in my app.js file:
.config(function($stateProvider, $urlRouterProvider, $ionicConfigProvider) {
$ionicConfigProvider.tabs.position('bottom');
$stateProvider
.state('tabs', {
url: '/tabs',
abstract: true,
templateUrl: 'templates/tabs.html'
})
.state('tabs.personal', {
url: '/personal',
views: {
'personalGoals-view': {
templateUrl: 'templates/personalGoals.html',
controller: 'personalCtrl'
}
}
})
.state('tabs.personalview', {
url: '/personalview',
templateURL: 'templates/test.html',
controller: 'personalViewCtrl'
})
.state('tabs.relationship', {
url: '/relationship',
views: {
'relationshipGoals-view': {
templateUrl: 'templates/relationshipGoals.html',
controller: 'relationshipCtrl'
}
}
})
.state('tabs.squad', {
url: '/squad',
views: {
'squadGoals-view': {
templateUrl: 'templates/squadGoals.html',
controller: 'squadCtrl'
}
}
});
// if none of the above states are matched, use this as the fallback
$urlRouterProvider.otherwise('tabs/dashboard');
});
You can see the full code over here.
Any help would be greatly appreciated, thank you in advance.
I think your problem is that you're trying to navigate to the wrong URL.
You are trying to navigate to the state name when you should be navigating to the state URL.
There are two ways to do this:
You can continue to use href, and change the URL to #/personalview
You can use ui-sref instead of href and do something like ui-sref="tabs.personalview"
You might check out the following for reference:
https://www.thepolyglotdeveloper.com/2014/11/using-ui-router-navigate-ionicframework/
https://www.thepolyglotdeveloper.com/2014/12/using-nested-states-angularjs-ui-router/
Best,

Angular ui-router: child state controller not getting called

In my Angular app, I have the following route structure:
.state('mapping', {
url: '/mapping',
templateUrl: 'app/components/mapping/mapping.html',
controller: 'MapCtrl as map',
abstract: true,
authenticate: true
})
.state('mapping.all', {
url: '',
templateUrl: 'app/components/mapping/partials/all.html',
authenticate: true
})
.state('mapping.project', {
url: '/:projectName',
templateUrl: 'app/components/mapping/partials/project.html',
controller: 'ProjectCtrl as proj',
authenticate: true
})
When accessing the mapping state, mapping.all loads by default. It basically shows a list of projects which link to the mapping.project state, as such:
<a ui-sref="mapping.project({projectId: project.id, projectName: project.name})">...</a>
I want to call the ProjectCtrl when I access mapping.project in order to load the necessary data, but it never even gets loaded. In the snippet below which includes only relevant data, the alert message never pops up:
angular
.module('watera')
.controller('ProjectCtrl', Controller);
Controller.$inject = ['$stateParams', 'UserFactory', 'ProjectFactory'];
function Controller($stateParams, UserFactory, ProjectFactory) {
var proj = this;
activate();
function activate() {
alert('1');
}
}
The js file is correctly linked and the controller is named correctly. The <div ui-view></div> element is placed within mapping.html, as seen below:
<div id="ribbon" class="no-print">
<div class="container-fluid">
<div class="row">
<div class="col-xs-12">
<strong>Mapping</strong>
<p class="text-muted">In this section...</p>
</div>
</div>
</div>
</div>
<div ui-view></div>
Why is this controller not loading?
EDIT: It gets weirder, I switched the structure to:
.state('mapping', {
url: '/mapping',
templateUrl: 'app/components/mapping/mapping.html',
abstract: true,
authenticate: true
})
.state('mapping.all', {
url: '',
templateUrl: 'app/components/mapping/partials/all.html',
controller: 'MapCtrl as map',
authenticate: true
})
.state('mapping.project', {
url: '/:projectName',
templateUrl: 'app/components/mapping/partials/project.html',
controller: 'ProjectCtrl as proj',
authenticate: true
})
And while MapCtrl keeps working correctly, ProjectCtrl still doesn't.
Found the issue... There were two instances of ProjectCtrl in this project:
Apparently, this causes some sort of silent conflict because there was absolutely no console error. Since the second instance was also linked on index.html, after the one that I wanted to load, it was probably simply replacing the correct version. Debugging nightmare.
Fixed now.
An abstract state cannot exist by definition so having a template URL for the parent and the children (which won't inherit the parent's templateUrl because the children define their own) is highly dubious IMO.
Im also wondering if there is trouble distinguising between ...
url: ''
AND
url: '/:projectName'
(Although it should handle the distinction).
However, to make sure I suggest a step-by-step approach. Kick off with the following mapping I suggest and then enhance it from there ...
.state('mapping', {
abstract: true,
authenticate: true
})
.state('mapping.all', {
url: '/',
templateUrl: 'app/components/mapping/partials/all.html',
controller: 'MapCtrl as map',
})
.state('mapping.project', {
url: '/project/:projectName',
templateUrl: 'app/components/mapping/partials/project.html',
controller: 'ProjectCtrl as proj',
})

Angular-ui-router doesn't have a default state and can't transition from it

I having some problems with the the angular-ui-router. When I click on a ui-sref I get the message
"Error: Could not resolve 'X' from state ''
transitionTo#http:/
Where X is the state in site-header that I'm trying to go to.
I think this means that there isn't a default state, but I'm not sure. In any case here are what I think are the relevant file parts:
index.html
<div class="container" ng-cloak>
<a ui-sref="home"></a>
<div ui-view></div>
</div>
app.config.js
angular.module('fTA')
.config(function($urlRouterProvider, $stateProvider) {
$urlRouterProvider.otherwise('/');
$stateProvider.state('home', {
url: '/',
template: '<p>This is home view</p>'
});
$stateProvider.state('login' {
url: '/login',
templateUrl: '/views/login.html',
controller: 'LoginCtrl'
});
});
Where /views/login.html are the path names of the files in my directory.
My understanding is that since urlRouterProvider is '/' then I should see <p>This is home view</p> in at '/'. But I don't. So, what retarded thing have I done so that even hard coded templates don't show up.
I just created a plunker here - and change only one thing: added comma after 'login'
$urlRouterProvider.otherwise('/');
$stateProvider.state('home', {
url: '/',
templateUrl: 'tpl.html'
});
// $stateProvider.state('login' {
$stateProvider.state('login', {
url: '/login',
templateUrl: 'tpl.html',
controller: 'LoginCtrl'
});
And this is working now:
<a ui-sref="home">home</a>
<a ui-sref="login">login</a>
The working plunker here

Categories

Resources