Abstract state with template in ionic - angularjs

I am working with ui-router AngularJS in Ionic Project. I have an abstract state where I nest my children's templates via <ion-nav-view> tag. The question is can I display some default data in the template of the abstract state that will be shown for all the children's templates ?? If no then Why. I tried this simple example
<ion-view view-title="MyView">
<div>
<h1>Welcome</h1>
</div>
<ion-nav-view name="ChildContent"></ion-nav-view>
</ion-view>
But the message Welcome is not shown. The space for the div is there but nothing is displayed.

I think I found the solution. What I ended with to not repeat the same info within all the children templates is to create a custom directive with its own template and just include this directive in every child's template. So, we just have one place to manipulate. It is the section "Template-expanding directive" in Angular documentation. More informations could be found in this link : enter link description here. Hope it will help someone else :) .

You can define a controller for your abstract state and there setear default values that can be displayed in various other views. You can also do this in the function
.state('app', {
url: '/app',
abstract: true,
templateUrl: 'templates/menu.html',
controller: 'AppCtrl'
})
.controller('AppCtrl', function($scope){
$scope.title = "Test title";
})
OR
angular.module('started.controllers', [])
.run(function($window, $rootScope) {
$rootScope.title = "Test title";
});
<ion-view view-title="{{title}}">
<div>
<h1>Welcome</h1>
</div>
<ion-nav-view name="ChildContent"></ion-nav-view>
</ion-view>

Related

Rendering the content of a page inside a div using ng-include based on the href of an element?

If I have two list items
<li></li>
<li></li>
and based on which is clicked, to use ng-include to render in a div on the current page?
<div ng-controller="main-panel" class="main-panel">
<ng-include src="'clickedElement'"></ng-include>
</div>
I am confused as to how to use routes to render an html inside a div, which is decided by which element you click?
main.config(function ($routeProvider, $locationProvider, $httpProvider) {
$routeProvider
.when('/', {
controller: 'side-menu'
})
.when('/signup', {
templateUrl : 'signup.html',
controller: 'main-panel'
});
$locationProvider.html5Mode(true);
});
HTML
<li ng-repeat="oucampus in secondaryLinks.oucampus">
<a ng-href='{{oucampus.href}}'> {{oucampus.title}} </a>
</li>
<div class="main-panel" ng-view></div>
CONTROLLER FUNCTION
oucampus: [
{title: "Requests", href:"signup.html"},
],
Plunker
If you are trying to render HTML content based on routes, you would want to use a routing service such as ngRoute or ui-router. ng-include isn't the best option for implementing routing within your angular application.
With ngRoute, you use a directive ng-view to have angular load html/controllers/etc based on route specified/configured in your applications config() method into some DOM element. This is triggered when you click on an <a> that has an ng-href with a corresponding path or programatically in something like a controller using the $location service path() method.
Route Configuration:
app.config(function($routeProvider) {
$routeProvider
.when('/foo', {
templateUrl: 'foo.html',
controller: 'FooController'
})
.when('/bar', {
templateUrl: 'bar.html',
controller: 'BarController'
});
});
HTML:
<ul>
<li><a ng-href="#/foo">foo</a></li>
<li><a ng-href="#/bar">bar</a></li>
</ul>
<div ng-view></div>
Here is a plunker demonstrating the functionality of basic routing including loading specific controllers and HTML templates based on a specific route.
ng-include
If you absolutely need to use ng-include, you can using a function executed via ng-click attached to $scope or controllerAs to update the src property of ng-include to load a template based on a click element. I've updated the plunker.
Hopefully this helps!

Controller executing twice with ui-router nested states (Ionic)

Problem
My Ionic app lets you choose a Project from the side menu, and then displays two tabs (Tasks, Messages) in the main content area. The tasks and messages tabs are nested states of project.
When you change projects in the side menu, TaskListCtrl gets executed twice. See the live demo and watch the console as you change between projects. I also have a video which shows the issue in detail.
How do I stop TaskListCtrl from executing twice? Is there a better way I could be structuring these nested states?
Code
Full code is on GitHub »
Here's my $stateProvider config:
.state('project', {
url: "/projects/:projectID",
abstract: true,
cache: false,
controller: 'ProjectDetailCtrl',
templateUrl: "templates/project.tabs.html",
resolve: {
project: function($stateParams, Projects) {
return Projects.get($stateParams.projectID);
}
}
})
.state('project.tasks', {
url: '/tasks',
views: {
'tasks-tab': {
templateUrl: 'templates/task.list.html',
controller: 'TaskListCtrl'
}
}
})
And the relevant snippet from controllers.js:
.controller('ProjectDetailCtrl', function($scope, project) {
$scope.project = project;
console.log('=> ProjectDetailCtrl (' + $scope.project.name + ')')
})
.controller('TaskListCtrl', function($scope, $stateParams) {
$scope.tasks = $scope.project.tasks;
console.log('\t=> TaskListCtrl')
console.log('\t\t=> $stateParams: ', $stateParams)
console.log('\t\t=> $scope.tasks[0].title: ', $scope.tasks[0].title)
})
Resources
Live demo (watch the console logs as you change between projects)
Video showing the issue
Code on GitHub
Notes
I am aware there are similar questions on StackOverflow — however, none of the solutions they offer solved my issue.*
I've read this can happen when attaching the controller both in $stateProvider and with ng-controller — however, I've checked and I'm not doing this. I'm only attaching the controller with $stateProvider.
I guess tuckerjt07 is right.
It seems to be an issue with routing and parameters and ionic tabs.
I've spend almost the whole day trying to figure out what is going on.
I thought the problem was with the fact you're using an abstract controller with parameters, but that's not the problem.
I've checked if the side menu was interfering with tabs but, again, the problem is not there.
I've checked the scope trying to eliminate friction using controllerAs and avoiding to reference the $scope object to store the viewmodel but ... nothing.
I've created a simplified version of your application here.
There's not much in there and the navigation is through constants in the header.
As you can see the problem is still there.
Doing a little bit of debugging it seems that the problem sits here.
That line calls the controller twice. You can check it yourself adding a breakpoint at line 48435 in ionic.bundle.js.
The only option you have is to change your project.tabs.html and load the list of tasks without the sub-view. Something like this:
<ion-view view-title="{{ project.name }}: Tasks">
<ion-tabs class="tabs-icon-top tabs-positive">
<ion-tab title="{{ project.name }} Tasks" icon="ion-home">
<ion-nav-view>
<ion-content>
<ion-list>
<ion-item class="item-icon-right" ng-repeat='task in project.tasks'>
{{ task.title }}
<i class="icon ion-chevron-right icon-accessory"></i>
</ion-item>
</ion-list>
</ion-content>
</ion-nav-view>
</ion-tab>
<ion-tab title="About" icon="ion-ios-football" ui-sref="tabs.tab2">
<ion-nav-view name="tabs-tab2"></ion-nav-view>
</ion-tab>
<ion-tab title="Another" icon="ion-help-buoy" ui-sref="tabs.tab3">
<ion-nav-view name="tabs-tab3"></ion-nav-view>
</ion-tab>
</ion-tabs>
</ion-view>
You can check how it works here.
I guess we should open an issue.

ui-route not redirecting to external page

From a modal dialog I present a general terms link that should redirect the user to a new page.
I would like to re-use my layout skeleton (background, logo ans basic styles) for the terms page, without the content of the master page (eg. search function, navigation etc). To achieve this I try to inject into a new window the terms template inside the ui-view="main" used for the normal site content (where is loaded the content of the modal dialog, as instance), but I get the error Could not resolve 'terms' from state 'login' (login is the current state where the modal dialog is).
Below the termsPage module with the ui-router state I would like to load:
angular.module('termsPage').config(function ($stateProvider) {
$stateProvider
.state('terms', {
url: '/terms',
views: {
'main': {
controller: 'TermsCtrl as Terms',
templateUrl: '/modules/staticPages/views/termsPage.html'
}
}
});
});
My index.html file:
<!-- Other tags excluded for sake of semplicity -->
<body ng-app="myApp">
<!-- Here I inject all the content -->
<div id="wrapper" ui-view="main">
</div>
Below the app module and view, where the content of the application is correctly loaded. Also the modal dialog from which I would like to redirect to the external page is loaded here.
angular.module('app').config(function($stateProvider){
$stateProvider
.state('app', {
url: '/app',
views:{
'main' : {
controller : 'AppCtrl',
templateUrl: 'modules/app/views/app.html'
}
}
});
});
Below app.html:
<div id="container">
<div class="browser">
<div class="content" ui-view="content" style="position:relative;">
</div>
My goal would be to create a sibling of app.html, injecting in main placeholder the content of my general terms page. Inside the modal dialog controller I use $state.go for the redirection:
$state.go('terms');
In my case the problem was that I did not registered the new module ('termsPage') as dependency in my main module:
angular.module('myApp', ['login','forms','termsPage'], function($urlRouterProvider){ ...}
Now that the module is registered, I can navigate correctly to state 'terms'.
Hopefully the case above might help someone else, getting hints for his/her case.

ionic - ion-nav-view not working

I am building a ionic pacakage, having multiple views. I use the route provider to navigate between different views.
app.js
.config(function($routeProvider,$locationProvider){
$routeProvider
.when('/search',
{
controller : 'MyController',
templateUrl : 'partials/search.html'
})
.when('/not-found/:className',
{
controller : 'MyController',
templateUrl : 'partials/not-found.html'
})
My index.html
<body ng-app="MyApp">
<ng-view></ng-view>
</body>
</html>
The problem is that the back button on my phone does not work.i.e it does not remember the history.
e.g If I go from search.html to not-found.html, when I press the back button on my phone, I expect it to come back to search.html instead it closes my app.
I looked and ionic forum and the suggest way to make back button work is to use ion-nav-view. If I replace ng-view with ion-nav-view, the search/not-found page are not rendering, I even tried adding the ion-view on the search/not-found html page.
1) Could you please suggest a way to get my back button working?
In order to achieve that, you actually need to capture the hardware back button pressed event and perform the navigation accordingly or You can use ion-nav-back-button..
Capture the hardware back button event :
$ionicPlatform.registerBackButtonAction(function () {
if (condition) {
navigator.app.exitApp();
} else {
// handle back action!
}
}, 100);
More Details can be found here
Using ion-nav-back-button
<ion-nav-bar>
<ion-nav-back-button class="button-clear">
<i class="ion-arrow-left-c"></i> Back
</ion-nav-back-button>
</ion-nav-bar>
More Details about this can be found here
registerBackButtonAction is already handled as part of ion-nav-back-button as part of the ng-click attribute within the ion-nav-back-button definition: buttonEle.setAttribute('ng-click', '$ionicGoBack()') , since $ionicGoBack executes $ionicHistory.goBack() which in turn handles the hardware back button. A simple change to use state configuration should work fine as below:
angular
.module('app', ['ionic'])
.config(function ($stateProvider, $urlRouterProvider) {
$stateProvider
.state('search', {
url: '/search',
controller : 'MyController',
templateUrl : 'partials/search.html'
})
.state('not-found', {
url: `/not-found/:className',
controller : 'MyController',
templateUrl : 'partials/not-found.html'
});
$urlRouterProvider.otherwise('/search');
});
HTML:
<body ng-app="app">
<ion-nav-bar>
<ion-nav-back-button></ion-nav-back-button>
</ion-nav-bar>
<ion-nav-view></ion-nav-view>
</body>
</html>

Angular JS - UI Routing - the script always scrolls down to the injection but I want them to see the whole page?

I am using a bootstrap template and I tried to implement Angular JS with ui.routing
The injection and navigation itself works fine... only my header includes a slider and the text is injected below. So every time someone access the route domain, he will by default get the home route; but after loading the site it automatically scrolls down to the injection part and the user does not see the header and the slider. How can I change that?
Here is part of my html code:
<header ng-include="'templates/header.html'"></header>
<div class="container">
<div class="row" >
<div ui-view></div>
</div>
<footer ng-include="'templates/footer.html'"></footer>
and here is my app.js
angular
.module('myApp', ['ui.router'])
.config(['$urlRouterProvider','$stateProvider',function($urlRouterProvider,$stateProvider){
$urlRouterProvider.otherwise('/');
$stateProvider
.state('home',{
url: '/',
templateUrl: 'templates/home.html'
})
.state('about',{
url: '/about',
templateUrl: 'templates/about.html'
})
.state('contact',{
url: '/contact',
template: 'CONTACT'
})
}])
You should use autoscroll="false" setting:
http://angular-ui.github.io/ui-router/site/#/api/ui.router.state.directive:ui-view
Example:
<div ui-view autoscroll="false"></div>
A cite:
autoscroll(optional) – {string=} –
It allows you to set the scroll behavior of the browser window when a view is populated.
And also few examples from doc:
<!-- If autoscroll present with no expression,
then scroll ui-view into view -->
<ui-view autoscroll/>
<!-- If autoscroll present with valid expression,
then scroll ui-view into view if expression evaluates to true -->
<ui-view autoscroll='true'/>
<ui-view autoscroll='false'/>
<ui-view autoscroll='scopeVariable'/>

Resources