Ionic tabs navigation issue - angular-ui-router

I'm using both of the Ionic framework and IU router to make a better navigation for you my first web application.
Here a simple architecture so you can easily understand the structure :
The problem I'm facing is that i'm not able to keep the state when navigating between tabs. for example. when I go to the next tab and click on next view and Press return, then I navigate to the first button, and when I go back to the second tab, I don't see the same state I left.
I can't resolve this problem.
here is a DEMO : PLUNKER DEMO + CODE
and this is my states code :
.config(function($stateProvider, $urlRouterProvider) {
$stateProvider
.state('live.today', {
url: '/today',
views: {
today: {
templateUrl: 'today_live.html',
}
}
})
.state('live.yesterday', {
url: '/yesterday',
views: {
yesterday: {
templateUrl: 'yesterday_live.html'
}
}
})
.state('live.tomorrow', {
url: '/tomorrow',
views: {
tomorrow: {
templateUrl: 'tomorrow_live.html'
}
}
})
.state('match.composition', {
url: '/composition',
views: {
view: {
templateUrl: 'composition.html'
}
}
})
.state('match.resume', {
cache: false,
url: '/resume',
views: {
view: {
templateUrl: 'resume.html'
}
}
})
.state('live', {
url: '/live',
views: {
live_view: {
templateUrl: 'live.html'
}
}
})
.state('match', {
cache: false,
url: '/match_details',
views: {
live_view: {
templateUrl: 'match_details.html'
}
}
})
.state('news', {
cache: false,
url: '/news',
views: {
news: {
templateUrl: 'news.html'
}
}
})
$urlRouterProvider.otherwise('/live/today');
})

Finally I've found a solution, which is to add " <ion-content> </ion-content> to the file where I have three tabs (live.html).
You can take a loot at the updated demo for someone who have the same complicated views architecture

Related

Upgrading from 0.9.19 to 1.1.0 seems to break Page objects

I have a page object with this code:
var MyToolComp = require('./MyToolComponent').MyToolComponent;
var MyToolCommand = {
get: function (cssLocator, timeout) {
return new MyToolComp({client: this, locator: cssLocator, timeout: timeout});
},
assertMyToolCount: function (expectedMyToolesCount, timeoutMs) {
console.log('Validate number of MyTool in the page to be [' + expectedMyToolesCount + ']');
this.waitForElementsCount(this.section.john_container.selector, expectedMyToolesCount, timeoutMs);
return this;
},
};
module.exports = {
commands: [MyToolCommand],
sections: {
john_container: {
selector: '.john_container',
elements: {
john_MyTool: {
selector: '.john_MyTool'
},
header: {
selector: '.john_MyTool_header'
}
}
},
multi_widget: {
selector: '.john_multi_widget'
}
}
};
After upgrading to 1.1.0, I can't run this code in my test:
var myToolPage = browser.page.myTool();
myToolPage.assertMyToolCount(1);
When debugging, I see myToolPage has "section" var, but no commands.
If I remove sections and only do
module.exports = MyToolCommand;
or
module.exports = {
commands: [MyToolCommand]
}
Then I can run
myToolPage.assertMyToolCount(1);
But then it failes since
this.section.john_container.selector
Isn't defined.
What am I doing wrong? I can't find anything here or here. Is there anything else I can read that'll help me? What else should I know when upgrading NW? (This is my first time seeing anything nightwatch-related so I kinda have to learn as I go).
Thanks in advance :)
The way I fixed this was replacing
module.exports = {
commands: [MyToolCommand],
sections: {
john_container: {
selector: '.john_container',
elements: {
john_MyTool: {
selector: '.john_MyTool'
},
header: {
selector: '.john_MyTool_header'
}
}
},
multi_widget: {
selector: '.john_multi_widget'
}
}
};
With
exports.commands = MyToolCommand;
exports.sections = {
john_container: {
selector: '.john_container',
elements: {
john_MyTool: {
selector: '.john_MyTool'
},
header: {
selector: '.john_MyTool_header'
}
}
},
multi_widget: {
selector: '.john_multi_widget'
}
};

Access Scope of elements in page object model

I am working on to automate a form to create a profile. While doing that I observed a something i need to understand. Please look at the code below and if it would be great if anyone can explain the reason behind this.
I am using page object for my project.
I have selectors defined under elements and i am accessing the elements/selectors in the functions down below.
I am not able to access the elements inside the function for the below code
For the this.api.perform function when I try to access the element(subjectGenderFemale) to click on it, it errors out with the error "ERROR: Unable to locate element: "#subjectGenderFemale" using: css selector". So i had to access it with the actual selector 'input[value="F"]'. Please refer to the code below # .api.perform.
'use strict';
var assert = require('assert');
var subjectJSON = require('../../../e2e/data/subjectData.json');
module.exports = {
elements: {
newSubjectButton: {
selector: '.btn.btn--primary'
},
subjectFirstName: {
selector: 'input[name^="first_name"]'
},
subjectLastName: {
selector: 'input[name^="last_name"]'
},
subjectDateOfBirth: {
selector: 'input[name^="date_of_birth"]'
},
subjectGenderFemale: {
selector: 'input[value="F"]'
},
subjectGenderMale: {
selector: 'input[value="M"]'
},
submitButton: {
selector: '.col.col-sm-offset-2.col-sm-8>div>form>button'
}
},
commands: [{
openCreateSubjectForm: function() {
return this
.waitForElementPresent('#newSubjectButton', 1000)
//the below href needs to change to proper element
.click('a[href="/subject/create"]')
},
populateSubjectForm: function() {
return this
.setValue('#subjectFirstName', subjectJSON["createSubject"]["firstName"])
.setValue('#subjectLastName', subjectJSON["createSubject"]["lastName"])
.setValue('#subjectDateOfBirth', subjectJSON["createSubject"]["dateOfBirth"])
.api.perform(function() {
if (subjectJSON["createSubject"]["gender"]=="F") {
this.api.click('input[value="F"]')
}else if (subjectJSON["createSubject"]["gender"]=="M") {
this.api.click('input[value="M"]')
}else if (subjectJSON["createSubject"]["gender"]=="Both") {
this.api.click('input[value="Both"]')
}else {
this.api.click('input[value="No preference"]')
}
})
},
submitCreateSubjectForm: function() {
return this.click('#submitButton');
}
}]
};
i got around this problem by accessing it via this.elements.subjectGenderFemale.selector

How to structure my states and routing in ui-router

I´m building a e-commerce site using angular1 and ui-router (1.0.0.beta3).
But I´m not sure how to setup this up.
This is what I have in mind.
const home = {
name: 'home',
url: '/',
views: {
header: 'header',
navbar: 'navbar',
sidenav: 'sideNav',
content: 'home'
}
};
const category = {
name: 'home.category',
url: '/{url}',
views: {
content: 'categoryPage'
}
};
const product = {
name: 'home.category.product',
url: '/{url}',
views: {
content: 'productPage'
}
};
we can´t control links that come from the cms it self, "/about-us" and "/category-x" can be a category or a cms-page so we added a route state where we can resolve the entity_type (product, category or cms-page)
.state('home.router', {
url: '/{url}?:{page:int}&:{limit:int}&:id',
params: {
limit: null,
category: null,
page: {
dynamic: true
},
id: {
dynamic: true
}
},
templateProvider: ['urlRewrite', function(urlRewrite) {
switch (urlRewrite.entity_type) {
case 'category':
return '<category-page limit="$stateParams.limit" page="$stateParams.page" category="{name: $resolve.urlRewrite.request_path, id: $resolve.urlRewrite.entity_id}"/>';
case 'product':
return '<product-page id="$resolve.urlRewrite.entity_id"/>';
case 'cms-page':
default:
return '<page url="$resolve.urlRewrite.target_path" />';
}
}],
resolve: {
urlRewrite: ['UrlRewrite', '$stateParams', function(UrlRewrite, $stateParams) {
return UrlRewrite.getUrlRewrite($stateParams.url);
}]
}
});
the problem is that category and route url patterns collide.
and we can´t really use parent/child inherits etc etc..
How should we go about resolving "unknown" urls?
Plunkr: http://plnkr.co/edit/gXzDO5j3arP8QCrpwL9k?p=preview
Let me provide you with the sample snippet. It will give you the idea.
appName.config(['$stateProvider','$urlRouterProvider', '$httpProvider' ,function ($stateProvider, $urlRouterProvider, $httpProvider) {
// $urlRouterProvider.otherwise('/login');
$urlRouterProvider.otherwise(function($injector, $location){
var state = $injector.get('$state');
var $localStorage = $injector.get('$localStorage');
if($localStorage.user){
return '/dashboard'
}else {
return '/login'
}
});
$stateProvider
.state('login', {
url: '/login',
views: {
'': {
templateProvider: function ($templateFactory, $localStorage) {
return $templateFactory.fromUrl(asset_path('angular/templates/base/login.html'));
},
controller: 'LoginCtrl'
}
}
})
$httpProvider.interceptors.push('Interceptor');
}]);

Parameter in $stateParams are undefined in resolve

I have a page showing a list of contact and clicking on one of the contacts in the view should switch to detail state as below:
dashboard-contacts-controller.js
vm.viewContact = function(contactId) {
console.log("Load contact " + contactId);
$state.go("app.dashboards_contact", {"id": contactId});
}
contacts-module.js
.state('app.dashboards_contact', {
url: '/dashboard-contact/:id',
views: {
'content#app': {
templateUrl: 'app/main/apps/dashboards/contacts/about/about.html',
controller: 'DashboardContactController as vm'
}
},
resolve: {
contact: ['DashboardContactsDataService', function($stateParams, DashboardContactsDataService) {
console.log($stateParams.id);
return DashboardContactsDataService.get($stateParams.id);
}
]
},
bodyClass: 'dashboard-contact'
});
$stateParams.id in resolve is always undefined.
You didnt inject $stateParams in resolve. Shouldn't it be
resolve: {
contact: ['$stateParams', DashboardContactsDataService', function($stateParams, DashboardContactsDataService) {
console.log($stateParams.id);
return DashboardContactsDataService.get($stateParams.id);
}
]
},

Display parent state templates while child dependencies resolve

My app has nested states and views. Parent states are abstract and reference header templates. I would like to define resolve dependencies in the child states and have the header templates display while those dependencies load. Currently the parent state and child state wait for the child dependencies to resolve.
Example code:
angular.module("Test", ["ui.router"])
.config(function($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise("/sec1");
$stateProvider.state("sec1", {
abstract: true,
url: "/sec1",
template: "<h1>Header 1</h1><div ui-view>Loading...</div>"
})
.state("sec1.page", {
url: "",
template: "<h1>Section 1 Page</h1><a ui-sref='sec2.page'>Goto 2</a>",
resolve: {
delay: function($timeout) {
return $timeout(function() {}, 1000);
}
}
})
.state("sec2", {
abstract: true,
url: "/sec2",
template: "<h1>Header 2</h1><div ui-view>Loading...</div>"
})
.state("sec2.page", {
url: "",
template: "<h1>Section 2 Page</h1><a ui-sref='sec1.page'>Goto 1</a>",
resolve: {
delay: function($timeout) {
return $timeout(function() {}, 1000);
}
}
});
});
Fiddle
Is there any way to display the template defined in the parent state while waiting for the dependencies defined in the child state to resolve?
You can just do this in the controller
app.controller('testctrl', function($rootScope) {
$scope.loading = true;
$scope.loadstuff = function() {
for (var i = 1; i < 100; i++) {
//load slow stuff
}
$scope.loading = false;
}
});
and in the view
<div ng-show="loading">Loading...</div>
<div ng-hide="loading" ng-init="loadstuff">content loaded</div>

Resources