Creating More Views with Ionic - javascript

I'm building a fairly basic Ionic / Cordova app. I've built 3 tabs and have some list items that link to other pages. I have no idea how to use routing properly.
My app.js
.state('tab.account.credit', {
url: '/account/credit',
views: {
'creditP': {
templateUrl: 'templates/credit.html',
controller: 'CreditCtrl'
}
}
})
My tab-account.html
<a class="item item-icon-left" ui-sref="tab.account.credit">
<i class="icon ion-bag"></i>
Credit!
</a>
My credit.html
<ion-view view-title="Credit!">
<ion-nav-bar class="bar-assertive">
<ion-content>
Please work
</ion-content>
</ion-view>
I tried another solution I found on SO, which was to create a <ion nav-view> element just below the <a> tag with class creditP. Which didn't work.
Any ideas how to get this to work?

Giving it the correct tab attribution under views and changing the href of the "Credit" link to #/account/credit seemed to have worked
.state('tab.credit', {
url: '/account/credit',
views: {
'tab-account': {
templateUrl: 'templates/credit.html',
controller: 'CreditCtrl'
}
}
})
But this is probably not the correct way to do this

Related

AngularJS UI Router: ui-sref not updating URL in address bar?

I'm building an AngularJS app and I'm using UI-Router in order to navigate through the app.
The flow of the web app consist in first registering or login, then it takes you to a main grid that has a lot of elements that are being displayed through ng-repeat and when you click in one of them it takes you to a dashboard that displays information of the element that has been clicked and it also successfully changes the path to index.html#!/dashboard/(here goes the name of the element)
This is the html 5 code of that main grid:
<div class="container">
<div class="row" ng-controller="ribtStateServicesController" >
<div class="col-md-3 ribt_HomeGrid" ng-repeat="estado in estados" >
<div class="img-ribt_overlay" >
<a ng-click="doWork(estado.idState)" ui-sref="dashboard({ribtNameState: estado.idState})">
<img src="{{estado.image}}" class="img-thumbnail">
<div class="ribt_overlay" ></div>
</a>
</div>
</div>
</div>
</div>
However, in that same dashboard I have a side menu, that has the same elements that were used in the main grid before. So I figured that it would take the same logic to be able to use the params that the UI-Router offer in order to change the URL and the content displayed. But it does nothing.
This is the code in the HTML of the dashboard's side menu:
<div class="col-md-6 nopadding" ng-repeat="estado in estados | filter:busqueda">
<md-card md-ink-ripple="#ffffff">
<img ng-src="{{estado.nolabel}}" class="md-card-image ribt_estado_side_img"
ui-sref="dashboard({ribtNameState: estado.idState})"
alt="Estado" ng-click="doWork(estado.idState); toggleLeft()">
<md-card-title class="nopadding">
<md-card-title-text>
<p class="ribt_card_estado_nombre">{{estado.nombre}}</p>
</md-card-title-text>
<md-menu>
<md-button class="md-icon-button float-right" aria-label="Share" ng-click="$mdMenu.open()">
<i class="material-icons">more_vert</i>
</md-button>
<md-menu-content width="4" ng-mouseleave="$mdMenu.close()">
<md-menu-item ng-repeat="item in [1, 2, 3]">
<md-button>
Option {{item}}
</md-button>
</md-menu-item>
</md-menu-content>
</md-menu>
</md-card-title>
</md-card>
</div>
Heres is the code in my app config:
ribtApp.config(function ($stateProvider,$mdThemingProvider,$locationProvider) {
$stateProvider
.state('login', {
url: '',
templateUrl: 'ribtComponents/ribtLogin/ribtLogin.html',
controller: 'ribtLoginController'
})
.state('home', {
url: '/home',
templateUrl: 'ribtComponents/ribtHome/ribtHome.html',
controller: 'ribtStateServicesController'
})
.state('dashboard', {
url: '/dashboard/{ribtNameState}',
templateUrl: 'ribtComponents/ribtDashboard/ribtDashboard.html',
controller: 'ribtStateServicesController',
resolve:{
ribtNameState: ['$stateParams', function($stateParams){
return $stateParams.ribtNameState;
console.log($stateParams.ribtNameState)
}]
}
});
I tried a console log to see if the param was being changed and it is but it does nothing to the URL path. I've tried a lot of code that I've found in stackoverflow but none of them has worked. I would be deeply thankful if you could help me with this.
You need to switch your ng-hrefs to ui-srefs, which is what ui-router uses to set up links to change states. So something like...
<div class="col-md-6 nopadding" ng-repeat="estado in estados | filter:busqueda">
[...]
<a ng-click="doWork(estado.idState)" ng-href="index.html#!/dashboard/{{estado.idState}}">
should be something more like...
<div class="col-md-6 nopadding" ng-repeat="estado in estados | filter:busqueda">
[...]
<a ng-click="doWork(estado.idState)" ui-sref="dashboard({ribtNameState: estado.idOrWhatever})">
with the caveat that I don't know what doWork is actually doing, so I don't know if that is necessary.
If you need to transition in a controller, you can also inject $state and use $state.go(...), but most of the time ui-srefs can get it handled in my experience.

AngularJS states and dynamic templates based on criteria

I'm trying to use AngularJS + ui-router in my project, it is working tho but I am in the middle of a situation here...
I have a HOME state with url /, and that state needs to do the following:
When user is NOT logged in, I want to show a full page with a login form and some different index.html because I don't need some columns and stuff.
When the user IS logged, then the default index.html should be used so I can use my ui-view grid system with all the cool stuff when a user is logged (navbar, search forms and a lot more which are in index.html as they must be shown in every page).
In order to check if the user is logged I have a factory AuthFactory.isUserLogged()
This is what I have done but is not exactly what I want...
index.html
<div ng-cloak="" ng-if="$root.globals.currentUser">
<div class="ui fixed inverted menu">
<div class="ui container">
<a class="header item" href=""><img class="logo" src="">Dashboard</a>
<a class="item">Link</a>
<div class="right menu">
<div class="ui dropdown icon item">
{{ $root.me.username }}
<div class="menu">
Settings
<div class="divider"></div>
Logout
</div>
</div>
</div>
</div>
</div>
<div class="pusher">
<div class="full height">
<div class="ui main container" ui-view="mainContainer"></div>
</div>
</div>
</div>
<div ng-cloak="" ng-if="!$root.globals.currentUser" ui-view="mainContainer"></div>
As you can see, ui-view="mainContainer" is declared twice in the same index.html one for user logged and one when not ($root.globals.currentUser)
app.js
$stateProvider
.state('home', {
url: '/',
views: {
'mainContainer': {
templateUrl: 'views/main.html',
controller: 'HomeCtrl',
controllerAs: 'vm'
}
}
})
I know this isn't a good solution, that's why I am asking for a better one...
PS: It doesn't really matter which index.html I use, I just don't need whole markup in my not-logged-home, just a simple login form without navbar and stuff
EDIT:
This isn't working, even the console.log, it doesn't output anything
.state('home', {
url: '/',
views: {
'mainContainer': {
templateUrl: function (AuthFactory) {
if (AuthFactory.isUserLogged()) {
console.log("yep");
return 'views/main.html';
}
console.log("nope");
return 'views/login.html';
}
}
}
})
Make two different state for login and home. When user is not logged in call login state and after login home page. Only one on master page.
Then for later transition after login you need to define another on home html page.
$stateProvider
.state('login',
{
url: '/login',
templateUrl: "Account/Login.html",
controller: 'LoginController'
})
.state('home',
{
url: '/home',
templateUrl: "Home/Home.html",
controller: 'HomeController'
})

How to load/render nested UI-Views in UI-Router

I have an application with one page called index.html. This page is the main page inside the application which I load my partials into.
Here is my Index.html:
<body>
<!--<div id="view" ng-view></div>-->
<div id="view" ui-view></div>
</body>
I want to load a Partial into this but then a partial into the partial i have just added.
The partial i want to add in is called dashboard.html and should be called when /dashboard routing is hit. Then I want to load a partial into the UI-View inside dashboard.html.
I don't know what other information I would need to supply to make this happen?
EDIT:
.state('dashboard', {
url: '/dashboard',
templateUrl: 'partials/dashboard.html',
controller: 'dashboard'
})
.state('dashboard.item', {
//url: '/dashboard/calender',
templateUrl: 'partials/calender.html',
controller: 'aceTrackerDash'
})
Its good to define nested states for this purpose . When the application is in a particular state — when a state is "active" — all of its ancestor states are implicitly active as well. Below, when the "contacts.list" state is active, the "contacts" state is implicitly active as well, because it's the parent state to "contacts.list" . So all nested defined views are loaded in their proper position:
Example :
$stateProvider
.state('contacts', {
templateUrl: 'contacts.html',
controller: function($scope){
$scope.contacts = [{ name: 'Alice' }, { name: 'Bob' }];
}
})
.state('contacts.list', {
templateUrl: 'contacts.list.html'
});
<!-- index.html -->
<body ng-controller="MainCtrl">
<div ui-view></div>
</body>
<!-- contacts.html -->
<h1>My Contacts</h1>
<div ui-view></div>
<!-- contacts.list.html -->
<ul>
<li ng-repeat="contact in contacts">
<a>{{contact.name}}</a>
</li>
</ul>
Plunker : http://plnkr.co/edit/7FD5Wf?p=preview
Also take a look at this :
Angular-UI Router: Nested Views Not Working

AngularJs controller not getting called when a link is clicked

Currently, I'm working on an initial AngularJs app for an Admin Console for a database. I'm pretty new at Angular, so I've started off by modifying the phonecat tutorial. Basically, I've got a Jersey REST API that I need to make calls against in Angular. CORS is not the problem, they're both running on the same Tomcat.
The data structure is Projects have Groups within them.
I can redirect from Login to the Projects list page, the controller for getting the list of projects is called, and I can click a project and get the details page and its controller is called. But when I click a link from the project-details page and have it redirect to the groups-list page, the REST api call is never made (according to Chrome's network monitor.)
I'm rather confused because hypothetically it should be the exact same as the projects list.
Controllers:
phonecatControllers.controller('ProjectListCtrl', ['$scope', '$http',function($scope, $http){
$http.get('http://localhost:8080/WrappingServer/rest/api/project?show_hidden=true').success(function(data){
$scope.projects = data.hits.hits
});
$scope.orderprop='timeModified';
}]);
phonecatControllers.controller('GroupListCtrl', ['$scope', '$http',function($scope, $http){
$http.get('http://localhost:8080/WrappingServer/rest/api/group?projectID='+$scope.project._id+'&show_hidden=true').success(function(data){
$scope.groups = data.hits.hits //Yes this is correct. It's an elasticsearch cluster.
});
$scope.orderprop='timeModified';
}]);
phonecatControllers.controller('ProjectDetailCtrl', ['$scope', '$routeParams' ,'$http', function($scope, $routeParams, $http){
$http.get('http://localhost:8080/WrappingServer/rest/api/project/'+$routeParams.projectId).success(function(data){
$scope.project=data;
});
}]);
project-details.html:
<img ng-src="{{project._source.imageUrl}}" class="project">
<h1>{{project._source.name}}</h1>
<p>{{project._id}}</p>
<ul class="specs">
<a ng-href="#/groups" ng-click=>Group IDs</a>
<dd ng-repeat="group in project._source.groupIDs">{{proj._source.name}}
{{group.groupID}}
</dd>
</ul>
group-list.html
<div class="container-fluid">
<div class="row">
<div class="col-md-2">
<!--Sidebar content-->
Search: <input ng-model="query">
Sort by:
<select ng-model="orderprop">
<option value="name">Alphabetical</option>
<option value="dateModified">Newest</option>
</select>
</div>
<div class="col-md-10">
<!--Body content-->
<ul class='groups'>
<li ng-repeat="group in groups | filter:query | orderBy:orderprop" class="thumbnail">
<img ng-src=" {{group._source.imageUrl}}" alt="{{group._source.name}}">
{{group._source.name}}
<p>{{group._source.timeModified}}</p>
</li>
</ul>
</div>
</div>
</div>
app.js
'use strict';
/* App Module */
var phonecatApp= angular.module('phonecatApp', [
'ngRoute', 'phonecatControllers', 'phonecatFilters']
);
phonecatApp.config(['$routeProvider',
function($routeProvider){
$routeProvider.when('/projects',
{
templateUrl: 'partials/project-list.html',
controller: 'ProjectListCtrl'
}).when('/projects/:projectId', {
templateUrl: 'partials/project-detail.html',
controller: 'ProjectDetailCtrl'
}).when('/home', {
templateUrl: 'partials/login.html',
controller: 'LoginCtrl'
}).when('/groups',
{
templateUrl: 'partials/group-list.html',
controller: 'GroupListCtrl'
})
.otherwise({
redirectTo: '/home'
});
}]);
I've even tried to take an approach where the projectID is a routeParam (kind of like for Project details), but still no luck.
Let me know if you anything else to answer my question. I know it's going to be something so stupidly simple that a handprint will appear on my forehead. (From what I've seen, possibly a space where it's not supposed to be.)
Thanks!
<a href="#/groups/{{group._id}}" class="thumb"> should be <a ng-href="/groups/{{group._id}}" class="thumb">
Also <a ng-href="#/groups" ng-click=>Group IDs</a should not have an empty ngClick on it. It should look like <a ng-href="/groups">.
So basically just change the attribute of the link from href to ng-href and then remove the # symbol from the link.
You have:
phonecatControllers.controller('GroupListCtrl', ['$scope', '$http',function($scope, $http){
$http.get('http://localhost:8080/WrappingServer/rest/api/group?projectID='+$scope.project._id+'&show_hidden=true').success(function(data){
$scope.groups = data.hits.hits //Yes this is correct. It's an elasticsearch cluster.
});
$scope.orderprop='timeModified';
}]);
I would instead do this in your controller:
phonecatControllers.controller('GroupListCtrl', ['$scope', '$http',function($scope, $http) {
$scope.function_name = function() {
$http.get('http://localhost:8080/WrappingServer/rest/api/group?projectID='+$scope.project._id+'&show_hidden=true').success(function(data){
$scope.groups = data.hits.hits //Yes this is correct. It's an elasticsearch cluster.
});
}
$scope.orderprop='timeModified';
}]);
For your link that is within the HTML element possessed by the controller,
<a ng-href="/groups" ng-click="function_name()">Group IDs</a>
As it is, your AJAX call is just sitting there. You need to place it within a block where code is executed for it to be called, just like in any other case. In this case, you must place it within a function that serves as a callback tied to ng-click.

Ionic - Re-use the same HTML template for multiple pages with different content

I am building an Ionic app with multiple pages. A lot of these pages have the same HTML structure, only the content differs. How can I just use one HTML file and fill the content dynamically? Is this done via a controller per page? Or is there a better way to do this?
Here is an example of the HTML code for one page:
<ion-view title="Comparison">
<div class="bar bar-subheader bar-stable">
<h5 class="text-center">Do you have many categories?</h5>
</div>
<ion-content class="has-subheader">
<ion-list>
<ion-item ui-sref="bar-chart" class="text-center">Yes</ion-item>
<ion-item ui-sref="column-chart" class="text-center">No</ion-item>
</ion-list>
</ion-content>
So the parts that need to be dynamic per page are the title, h5 and list items.
Now I have a separate HTML file per page. I then refer to these HTML files in the .state in app.js as shown below.
.state('comparison-nb-categories', {
url: '/',
templateUrl: 'templates/comparison/nb-categories.html'
})
That page can be accessed from another page via an ui-sref as shown below.
<ion-item ui-sref="comparison-nb-categories" class="text-center">No</ion-item>
I think you can use one template html for all such pages but different controllers and in this controllers assign right values to model.
.state('state1', {
templateUrl: "templates/page1.html",
controller: "FirstCtrl",
})
.state('state2', {
templateUrl: "templates/page1.html",
controller: "SecondCtrl",
});
html would be
<ion-view title="{{title}}">
<div class="bar bar-subheader bar-stable">
<h5 class="text-center">{{subheader}}</h5>
</div>
<ion-content class="has-subheader">
<ion-list ng-repeat="item in items">
<ion-item ui-sref="{{item.ref}}bar-chart" class="text-center">{{item.name}}</ion-item>
</ion-list>
</ion-content>
FirstCtrl
.controller('FirstCtrl', ['$scope', function ($scope) {
$scope.title = Title1;
$scope.subheader = Subheader1;
$scope.items = [{name:'Yes', ref:'bar-chart'},{name:'No', ref:'column-chart'}];
SecondCtrl
.controller('SecondCtrl', ['$scope', function ($scope) {
$scope.title = Title2;
$scope.subheader = Subheader2;
$scope.items = [{name:'name1', ref:'ref1'},{name:'name2', ref:'ref2'}];
I added working example http://codepen.io/anon/pen/bEpKJE?editors=101

Categories