The $scope data is not displaying on the page.
I have 2 views that are using the same controller.
I have this view, and I'm clicking the edit issue button
<div class="container" data-ng-init="adminInit()">
<div class="row">
<div class="col-lg-12">
<div class="page-header text-center">
<h1>Issues Admin</h1>
<button type="button" class="btn btn-primary" ui-sref="add-issue">
Add Issue
</button>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
<h3>Current Issues</h3>
<ul ng-repeat="issue in issues">
<li>
<strong>{{issue.title}}</strong> - Current Status:
<strong>{{issue.status}}</strong>
<div ng-hide="true" class="btn btn-xs btn-primary glyphicon glyphicon-pencil" ng-click="editIssue(issue._id)"></div>
<div class="btn btn-xs btn-primary glyphicon glyphicon-pencil" ng-click="editIssue(issue._id)"></div>
<div class="btn btn-xs btn-danger glyphicon glyphicon-remove" ng-click="deleteIssue(issue._id)"></div>
</li>
<ul>
<li>{{issue.description}}</li>
<li>Issue Logged at: {{issue.timestamp | date:'MM/dd/yyyy # h:mma'}}</li>
</ul>
</ul>
</div>
</div>
</div>
And this in my controller
$scope.editIssue = function(id) {
$state.go('edit-issue');
$http.get(Configuration.API + 'api/issue/' + id)
.then(function successCallback(response) {
$scope.issueToEdit = response.data;
console.log($scope.issueToEdit);
});
};
then the edit-issue view
<div class="container">
<div class="row">
<div class="col-lg-12">
<div class="page-header text-center">
<h1>Edit Issue</h1>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
<form name="frm" ng-submit="updateIssue()">
<div class="form-group">
<label for="editIssueTitle">Issue Title</label>
<input type="text" name="editIssueTitle" id="editIssueTitle" class="form-control" ng-model="issueToEdit.title" required/>
</div>
<div class="form-group">
<label for="editIssueDesc">Issue Description</label>
<textarea name="editIssueDesc" id="editIssueDesc" class="form-control" cols="60" rows="16" ng-model="issueToEdit.description" required></textarea>
</div>
<div class="form-group">
<label for="editIssueStatus">Issue Status</label>
<select name="editIssueStatus" id="editIssueStatus" class="form-control" ng-model="issueToEdit.status" required>
<option value="Identified">Identified</option>
<option value="Investigating">Investigating</option>
<option value="Monitoring">Monitoring</option>
<option value="Resolved">Resolved</option>
</select>
</div>
<button class="btn btn-default" ng-disabled="frm.$invalid">Go</button>
</form>
</div>
</div>
</div>
But the issueToEdit data is never displayed
The console.log line displays the right data
{
"_id": "58135b6e3987b8a90c4fc15b"
"title": "Test"
"description": "Testset"
"timestamp": "2016-10-28T14:06:38.284Z"
"status": "Monitoring"
"__v": 0
}
Any idea why this is happening?
EDIT: Let me clarify a little, when I land on the edit-issue page, I want the issueToEdit data to displayed in the form so that I can then update the info and then save it.
EDIT2: Here is my full controller and app.js
app.controller('issuesController', ['$scope', '$http', '$state', '$interval', 'auth', 'Configuration', function($scope, $http, $state, $interval, auth, Configuration) {
$scope.isLoggedIn = auth.isLoggedIn;
$scope.getIssues = function() {
console.log('retrieving issues');
$http.get(Configuration.API + 'api/issue')
.success(function(data) {
$scope.issues = data;
})
.error(function(data) {
console.log('Error: ' + data);
});
};
$scope.addIssue = function() {
var nIssue = {
'title': $scope.newissue.title,
'description': $scope.newissue.description,
'timestamp': new Date(),
'status': $scope.newissue.status
}
$http.post(Configuration.API + 'api/issue', nIssue)
.success(function(data) {
$state.go('admin');
})
.error(function(data) {
console.log('Error: ' + data);
});
};
$scope.editIssue = function(id) {
$state.go('edit-issue');
$http.get(Configuration.API + 'api/issue/' + id)
.then(function successCallback(response) {
$scope.issueToEdit = response.data;
console.log($scope.issueToEdit);
});
};
$scope.updateIssue = function() {
//ToDo add this logic
};
$scope.deleteIssue = function(id) {
$http.delete(Configuration.API + 'api/issue/' + id)
.success(function(data) {
$scope.issues = data;
})
.error(function(data) {
console.log('Error: ' + data);
});
};
$scope.adminInit = function() {
$scope.getIssues();
$interval($scope.getIssues, 60000);
};
$scope.issueInit = function() {
$scope.getIssues();
$interval($scope.getIssues, 60000);
$(".devInfo").text(navigator.userAgent);
$(".flashVersion").text(FlashDetect.raw);
};
}]);
app.js
var app = angular.module('supportWebsite', ['ui.router']);
app.config(['$stateProvider', '$urlRouterProvider', '$locationProvider', function($stateProvider, $urlRouterProvider, $locationProvider) {
$urlRouterProvider.otherwise('/articles');
$stateProvider
.state('home', {
url: '/',
templateUrl: '/pages/issues/index.html',
controller: 'issuesController'
})
.state('admin', {
url: '/admin',
templateUrl: '/pages/issues/admin/index.html',
controller: 'issuesController',
onEnter: ['$state', 'auth', function($state, auth) {
if (!auth.isLoggedIn()) {
$state.go('login');
}
}]
})
.state('add-issue', {
url: '/admin/add-issue',
templateUrl: '/pages/issues/admin/add.html',
controller: 'issuesController',
onEnter: ['$state', 'auth', function($state, auth) {
if (!auth.isLoggedIn()) {
$state.go('login');
}
}]
})
.state('edit-issue', {
url: '/admin/edit-issue',
templateUrl: '/pages/issues/admin/edit.html',
controller: 'issuesController',
onEnter: ['$state', 'auth', function($state, auth) {
if (!auth.isLoggedIn()) {
$state.go('login');
}
}]
});
$locationProvider.html5Mode(true);
}]);
Your method tells the $state service to go to another state. That will replace the view by the view associated with the new state, create a new $scope, and a new controller instance using this new $scope.
So whatever you put in the $scope of the current controller is irrelevant and useless: the other state uses another $scope and another controller.
You need to pass the ID of the issue to edit as a parameter of the new state. And the controller of this new state (or one of its resolve functions) should use that ID to get the issue to edit.
If you want to stay on the same view, using the same controller and the same scope, then you shouldn't navigate to another state.
Related
I have this app that get some data about weather in specific region:
And I want to change the current temperature from Celsius to Fahrenheit by just clicking on the the C/F buttons. I tried the following script:
In app.JS and inside the controller of the current page:
$scope.convertToFahrenheit = function(degF)
{
return Math.round(1.8*(degF - 273) +32);
}
Now in the html page I did the following:
Degree:
<button ng-click="convertToCelsius(w.temp.day)" class="btn btn-info">
C
</button> |
<button ng-click="convertToFahrenheit(w.temp.day)" class="btn btn-info">
F
</button>
This is the all app.JS script:
// MODULE
var weatherApp = angular.module('weatherApp', ['ngRoute', 'ngResource']);
// ROUTES
weatherApp.config(function ($routeProvider) {
$routeProvider
.when('/', {
templateUrl: 'pages/home.htm',
controller: 'homeController'
})
.when('/forecast', {
templateUrl: 'pages/forecast.htm',
controller: 'forecastController'
})
.when('/forecast/:days', {
templateUrl: 'pages/forecast.htm',
controller: 'forecastController'
})
});
//Services
weatherApp.service('cityService', function()
{
this.city = 'Rayak, ZA';
});
// CONTROLLERS
weatherApp.controller('homeController', ['$scope', 'cityService', function($scope, cityService) {
$scope.city = cityService.city;
//We are going to watch if the city text box is changed and updated the service
$scope.$watch('city', function()
{
cityService.city = $scope.city;
});
}]);
weatherApp.controller('forecastController', ['$scope', '$resource', '$routeParams', 'cityService', '$log', function($scope, $resource, $routeParams, cityService, $log) {
$scope.city = cityService.city;
$scope.weatherApi = $resource("http://api.openweathermap.org/data/2.5/forecast/daily?APPID=fcbc7173d3b696941002572f3f807129",
{callback: "JSON_CALLBACK"}, {get:{method: "JSONP"}});
$scope.days = $routeParams.days || 2;
$scope.weatherResult = $scope.weatherApi.get({q: $scope.city, cnt: $scope.days})
$log.log($scope.weatherResult);
$scope.convertToCelsius = function(degC)
{
return Math.round(degC - 273.15);
}
$scope.convertToFahrenheit = function(degF)
{
return Math.round(1.8*(degF - 273) +32);
}
$scope.convertToDate = function(toDate)
{
return new Date(toDate*1000);
}
}]);
And here is the forecast.htm script:
<label class="label label-info">Forecast for {{ city }} </label>
<hr/>
Days: 2 | 5 | 10
Degree: <button ng-click="convertToCelsius(w.temp.day)" class="btn btn-info">C</button> | <button ng-click="convertToFahrenheit(w.temp.day)" class="btn btn-info">F</button>
<div ng-repeat="w in weatherResult.list">
<div class="row">
<div class="col-md-6">
<div class="panel panel-info">
<div class="panel-heading">
<h3 class="panel-title">{{ convertToDate(w.dt) | date: 'MMM, d, y' }}</h3>
</div>
<div class="panel-body">
<div class="col-sm-3">
{{w.temp.weather.icon}}
</div>
<hr/>
Daytime temperature {{convertToCelsius(w.temp.day)}}
</div>
</div>
</div>
</div>
</div>
The convertToCelsius() is working properly, and I tried to get the convertToFahrenheit() function inside the ng-repeat because the w is inside of it, but still no changes.
You have to store in the scope what kind of values to display and then use convertToCelsius or convertToFahrenheit according to that variable. So in your app.js, in forecastController add the following line
$scope.display = 'C';
Then change your buttons like this
<button ng-click="display = 'C'" class="btn btn-info">C</button> | <button ng-click="display = 'F'" class="btn btn-info">F</button>
And display the temp like this
Daytime temperature {{display == 'C'?convertToCelsius(w.temp.day):convertToFahrenheit(w.temp.day)}}
The display variable will decide if the temp will display as Celsius or Fahrenheit
hope this helps,
John
Trying to get my form inputs into my controller so that I can pass them in my API call.
I have this form:
<ion-content class="has-subheader">
<form ng-submit="storeProject()">
<div class="list">
<label class="item item-input">
<span class="input-label">Title</span>
<input type="text" ng-model="projectData.title">
</label>
<label class="item">
<button class="button button-block button-positive" type="submit">Create Project</button>
</label>
</div>
</form>
</ion-content>
I then have this controller:
.controller('ProjectCtrl', function($scope, $auth, $http, $ionicPopup, $rootScope) {
$scope.projectData = {};
$scope.storeProject = function(projectData) {
console.log("add project: ", $scope.projectData);
};
})
And this in my app.js:
.state('app.new_project', {
url: '/projects/new',
data: {
permissions: {
except: ['anonymous'],
redirectTo: 'app.auth'
}
},
views: {
'menuContent': {
templateUrl: 'templates/new_project.html',
controller: 'ProjectCtrl'
}
}
});
I have my API working great, but just need to be able to get my values from the form to post.
Need to be able to do projectData.title etc.
I always get undefined in the log.
Replace
$scope.storeProject = function(projectData) {
by
$scope.storeProject = function() {
Or replace
ng-submit="storeProject()"
by
ng-submit="storeProject(projectData)"
That said, I don't see how your posted code could log undefined. My guess is that your actual code is
console.log("add project: ", projectData);
I wrote a code for for my app, when a I click on the toggle to reach the second page, the url changes it took me there but nothing is appeared, just a blank page no more,
here is the app.js code
angular.module("BloodDonationApp", [
"ionic",
])
.run(function ($ionicPlatform) {
$ionicPlatform.ready(function () {
if (window.cordova && window.cordova.plugins && window.cordova.plugins.keyboard) {
cordova.plugins.keyboard.hidekeyboardAccessoryBar(true);
}
if (window.statusBar) {
//org.apache.cordova.statusbar required
statusbar.styleDefault();
}
});
})
//****************ROUTES***************//
.config(function ($stateProvider, $urlRouterProvider) {
$stateProvider
.state('home', {
abstarct: true,
url: "/home",
templateUrl: "templates/home.html"
})
.state('home.feeds', {
url: "/feeds",
views: {
"tab-feeds": {
templateUrl: "templates/feeds.html"
}
}
})
.state('home.settings', {
url: "/settings",
views: {
"tab-settings": {
templateUrl: "templates/settings.html"
}
}
})
.state('requestDetails', {
url: "/RequestDetails/:id",
view: {
"mainContent": {
templateUrl: "templates/requestDetails.html"
}
}
})
.state('requestDetails.ClientRegister', {
url: "/Client-Register/:id",
view: {
"mainContent": {
templateUrl: "templates/ClientRegister.html"
}
}
});
//if name of the above states are matched, use this as the fallback
$urlRouterProvider.otherwise('/home/feeds');
})
and here is the html code of the feeds page:
<ion-view ng-controller="FeedsCtrl as vm">
<ion-content class="has-header">
<div class="card" ng-repeat="requests in vm.feeds">
<div class="item item divider" ng-click="toggleGroup(requests)"
ng-class="{active: isGroupShown(requests)}">
<div class="row row-bottom">
<div class="col">
{{requests.type}}
</div>
<div class="col">
{{requests.unitNb}} Units
</div>
</div>
</div>
<div class="item-accordion"
ng-show="isGroupShown(requests)" ng-click="goToDetails()">
<div class="row">
<div class="col-top">
Since 7 s{{requests.Date}}
</div>
<div class="col col-center col-50 col-offset-8">
<br/>{{requests.HospName}}
<br/>
{{requests.Hosplocation}}
</div>
<div class="col col-bottom">
<a class="item item-icon-right">
<div class="row">
<i class="ion-icon ion-pinpoint "></i>
</div>
<div class="row">
{{requests.HospDistance}}4km
</div>
</a>
</div>
</div>
</div>
</div>
</ion-content>
</ion-view>
and the controller for feeds:
(function () {
'use strict';
angular.module('BloodDonationApp')
.controller('FeedsCtrl', ['BloodDonationApi', '$scope', '$state', FeedsCtrl]);
function FeedsCtrl(BloodDonationApi, $scope, $state) {
var vm = this;
//start Data Binding functions//
var data = BloodDonationApi.getRequests();
console.log(data);
vm.feeds = data;
//end Data Binding//
//start Accordion function//
$scope.toggleGroup = function (requests) {
if ($scope.isGroupShown(requests)) {
$scope.shownGroup = null;
} else {
$scope.shownGroup = requests;
}
}
$scope.isGroupShown = function (requests) {
return $scope.shownGroup === requests;
}
$scope.goToDetails = function() {
$state.go('requestDetails', {id : 5});
}
//end Accordion function//
};
})();
but the request details is not appeared after clicking on the toggle its just give a blanck page, the html code :
<ion-view ng-controller="RequestDetailsCtrl as vm">
<ion-content class="has-header">
<div class="card">
<div class="item">
<div class="row">
<div class="col">
{{requests.type}}
</div>
<div class="col">
{{requests.unitNb}} Units
</div>
</div>
<div class="row">
<div class="col">
{{requests.HospName}}
</div>
<div class="col">
{{requests.Hosplocation}}
</div>
<div class="col">
4 Km Away
</div>
</div>
<button class="button button-block button-positive">
Yes, I donate <i class="ion-icon ion-thumbsup"></i>
</button>
<label>
4/5 <i class="ion-icon ion-battery-half"></i>
</label>
<div class="title">
<h3>
Last time I'd donated was since<br /> 4 months
<i class="ion-icon ion-checkmark-round"></i>
</h3>
</div>
</div>
</div>
</ion-content>
</ion-view>
the controller:
(function () {
'use strict';
angular.module('BloodDonationApp')
.controller('RequestDetailsCtrl', ['BloodDonationApi', '$stateParams', '$scope', RequestDetailsCtrl]);
function RequestDetailsCtrl(BloodDonationApi, $stateParams, $scope) {
var vm = this;
var data = BloodDonationApi.getRequests();
console.log(data);
vm.requestDetails = data;
console.log("$stateParams", $stateParams.id);
//end Data Binding//
// Get you request
};
})();
am sure that there is an error with the view code, but m not figuring it out, if anybody can help me plz.
You are inside a nested state when you are tying to load requestDetails so change your state to :
.state('requestDetails', {...})
.state('home.requestDetails', {
url: "/feeds/:id",
views: {
'tab-feeds' :{
templateUrl: "templates/requestDetails.html"
}
}
})
and your method to:
$scope.goToDetails = function() {
$state.go('home.requestDetails', {id : 5});
}
and It's working !
I've fork your git so updated working version is here if you want to pull
I'm creating a single page app in which a user searches for a term, the result gets saved in a variable, and a new page is routed that displays the result. I have this functionality working, however I want the variable to be cleared when the user returns to the previous page and most importantly when the user logs out. What's the proper way to do this? I want the factory to save things for certain pages that I want, and clear them for certain pages I don't want like "home" or "logout".
Factory:
angular.module('firstApp')
.factory('fact', function () {
var service = {};
var _information = 'Default Info';
service.setInformation = function(info){
_information = info;
}
service.getInformation = function(){
return _information;
}
return service;
});
Controller:
angular.module('firstApp')
.controller('InformationCtrl', function($scope, $http, $location, fact) {
$scope.message = 'Hello';
$scope.result = fact.getInformation();
$scope.sub = function(form) {
console.log($scope.name);
$scope.submitted = true;
$http.get('/wiki', {
params: {
name: $scope.name,
}
}).success(function(result) {
console.log("success!");
$scope.result = result;
fact.setInformation(result);
$location.path('/informationdisplay');
});;
}
});
Routes
angular.module('firstApp')
.config(function ($routeProvider) {
$routeProvider
.when('/information', {
templateUrl: 'app/information/input.html',
controller: 'InformationCtrl',
authenticate : true
})
.when('/informationdisplay', {
templateUrl: 'app/information/results.html',
controller: 'InformationCtrl',
authenticate : true
});
});
input.html
<div class="row">
<div class="col-md-6 col-md-offset-3 text-center">
<p>{{result}}</p>
<form class="form" name="form" ng-submit="sub(form)" novalidate>
<input type="text" name="name" placeholder="Name" class="form-control" ng-model="name">
</br>
<button class="btn btn-success" type="submit" class="btn btn-info">Check</button>
</div>
</div>
results.html
<div ng-include="'components/navbar/navbar.html'"></div>
<div class="row">
<div class="col-sm-4 col-sm-offset-4">
<h2>Information Results</h2>
<p>{{result}}</p>
</div>
</div>
</div>
If you want it to wipe the value when they change routes (which logout should change routes also, I assume), you can watch the $routeChangeStart event and have it wipe the value whenever it occurs. You put that function in the module.run block:
app.run(function ($rootScope, fact) {
$rootScope.$on("$routeChangeStart",function(event, next, current){
fact.setInformation(null);
});
});
I am using ui.router to create my views and I have set up this set of states:
.config(['$stateProvider', function ($stateProvider) {
// Set up our state(s)
$stateProvider.state('designer', {
url: '/:sport/designer',
abstract: true,
templateUrl: '/app/designer/index.tpl.html',
controller: 'DesignerController',
controllerAs: 'controller'
}).state('designer.team', {
url: '',
templateUrl: '/app/designer/team.tpl.html',
data: {
pageTitle: 'Create your team'
}
}).state('designer.kit', {
url: '/kit',
templateUrl: '/app/designer/kit.tpl.html',
data: {
pageTitle: 'Choose your garments'
}
}).state('designer.design', {
url: '/design',
templateUrl: '/app/designer/design.tpl.html',
data: {
pageTitle: 'Choose your design'
}
}).state('designer.refine', {
url: '/refine',
templateUrl: '/app/designer/refine.tpl.html',
data: {
pageTitle: 'Refine your design'
}
}).state('designer.order', {
url: '/order',
templateUrl: '/app/designer/order.tpl.html',
data: {
pageTitle: 'Order your kit'
}
}).state('designer.save', {
url: '/save',
templateUrl: '/app/designer/save.tpl.html',
data: {
pageTitle: 'Save your kit',
requireLogin: true
}
});
}])
The index template looks like this:
<div class="container designer">
<div class="row designer-header">
<div class="col-md-6" ng-include="'/app/designer/tpls/header.tpl.html'">
</div>
<div class="col-md-6" ng-include="'/app/designer/tpls/navigation.tpl.html'">
</div>
</div>
<div class="row">
<div class="col-md-12" ng-include="'/app/designer/tpls/total.tpl.html'" ng-hide="controller.garments.loading">
</div>
</div>
<div class="row designer-body">
<ui-view></ui-view>
</div>
</div>
The navigation include looks like this:
<nav class="navbar navbar-designer">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
</div>
<div class="collapse navbar-collapse" id="designer-menu">
<ul class="nav navbar-nav navbar-right">
<li ui-sref-active="active"><a ui-sref=".team">Your team</a></li>
<li><a>|</a></li>
<li ui-sref-active="active"><a ui-sref=".kit">Kit</a></li>
<li><a>|</a></li>
<li ui-sref-active="active"><a ui-sref=".design">Design</a></li>
<li><a>|</a></li>
<li ui-sref-active="active"><a ui-sref=".refine">Refine</a></li>
<li><a>|</a></li>
<li ui-sref-active="active"><a ui-sref=".order">Order</a></li>
</ul>
</div>
</nav>
So, the idea is that I want to build this in steps; i.e. When the page is first loaded I would like the user to only be able to advance to the next step (.kit) when they have filled in the first page, which looks like this:
<div class="col-md-12">
<div class="alert alert-warning alert-dismissable" ng-show="controller.colours.data && controller.colours.data.length === 0">
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button>
You must have at least one colour in the database before you can create a team / kit.
</div>
<alert-error error="controller.colours.error"></alert-error>
<form name="teamForm" novalidate ng-show="!controller.colours.loading && !controller.colours.error">
<div class="form-group">
<label class="sr-only" for="teamName">Team name</label>
<div class="input-group">
<div class="input-group-addon">1</div>
<input type="text" class="form-control" id="teamName" placeholder="Enter your team name" ng-model="controller.model.team.data.name" ng-change="controller.saveSession()" required>
</div>
</div>
<div class="form-group">
<label class="sr-only" for="colours">Colours</label>
<div class="picker colour-picker">
<div class="input-group">
<div class="input-group-addon">2</div>
<input type="text" class="form-control" id="colours" placeholder="Choose your colours" disabled>
</div>
<ul class="picker-dropdown list-inline form-control">
<li ng-repeat="colour in controller.colours.data" ng-class="{ 'active': controller.matchColour(colour) }">
<a href style="background-color: #{{ colour.hex }};" ng-click="controller.setColour(colour)"></a>
</li>
</ul>
</div>
</div>
</form>
<p><a class="btn btn-primary pull-right" ui-sref="designer.kit">Choose teamwear</a></p>
</div>
All the other "tabs" should be disabled. And then similarly, when I advance to the kit view I would like the user only to be able to advance when they have made a selection, this is the kit page:
<div class="col-md-12">
<div class="alert alert-warning alert-dismissable" ng-show="controller.garments.data && controller.garments.data.length === 0">
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button>
It appears that your sport does not have any garments associated with it.
</div>
<alert-error error="controller.garments.error"></alert-error>
<form ng-show="!controller.garments.loading && !controller.garments.error">
<div class="form-group">
<label class="sr-only" for="clubName">Club name</label>
<div class="input-group">
<div class="input-group-addon">1</div>
<input type="text" class="form-control" id="clubName" placeholder="Choose your teamwear">
</div>
</div>
<div class="picker garment-picker">
<ul class="picker-dropdown list-inline">
<li ng-repeat="garment in controller.garments.data" ng-class="{ 'active': controller.matchGarment(garment) }"><a href ng-click="controller.setGarment(garment)">{{ garment.title }}</a></li>
</ul>
</div>
</form>
<p><a class="btn btn-primary pull-right" ui-sref="designer.design">Design teamwear</a></p>
</div>
Does anyone know how I could do this?
I can provide more information if needed.
I have answered this myself with the aid of resolve.
Here are my states now:
// Set up our state(s)
$stateProvider.state('designer', {
url: '/:sport/designer',
abstract: true,
templateUrl: '/app/designer/index.tpl.html',
controller: 'DesignerController',
controllerAs: 'controller',
resolve: {
model: ['DesignerService', function (service) {
console.log('hi');
// return our model
return service.get();
}]
}
}).state('designer.team', {
url: '',
templateUrl: '/app/designer/team.tpl.html',
data: {
pageTitle: 'Create your team'
}
}).state('designer.kit', {
url: '/kit',
templateUrl: '/app/designer/kit.tpl.html',
data: {
pageTitle: 'Choose your garments'
},
resolve: {
model: ['$q', 'DesignerService', function ($q, service) {
// Defer our promise
var deferred = $q.defer();
// Get our model
var model = service.get();
// If we have selected our colours and our team name
if (model.team.data.colours.length > 0 && model.team.data.name) {
// resolve our promise
deferred.resolve(model);
} else {
// Otherwise reject our promise
deferred.reject();
}
// Return our promise
return deferred.promise;
}]
}
}).state('designer.design', {
url: '/design',
templateUrl: '/app/designer/design.tpl.html',
data: {
pageTitle: 'Choose your design'
},
resolve: {
model: ['$q', 'DesignerService', function ($q, service) {
// Defer our promise
var deferred = $q.defer();
// Get our model
var model = service.get();
// If we have selected any garments
if (model.kit.data.garments.length > 0) {
// resolve our promise
deferred.resolve(model);
} else {
// Otherwise reject our promise
deferred.reject();
}
// Return our promise
return deferred.promise;
}]
}
}).state('designer.refine', {
url: '/refine',
templateUrl: '/app/designer/refine.tpl.html',
data: {
pageTitle: 'Refine your design'
},
resolve: {
model: ['$q', 'DesignerService', function ($q, service) {
// Defer our promise
var deferred = $q.defer();
// Get our model
var model = service.get();
// If we have selected our design
if (model.kit.data.design) {
// resolve our promise
deferred.resolve(model);
} else {
// Otherwise reject our promise
deferred.reject();
}
// Return our promise
return deferred.promise;
}]
}
}).state('designer.order', {
url: '/order',
templateUrl: '/app/designer/order.tpl.html',
data: {
pageTitle: 'Order your kit'
},
resolve: {
model: ['$q', 'DesignerService', function ($q, service) {
// Defer our promise
var deferred = $q.defer();
// Get our model
var model = service.get();
// TODO: check for the applied colours
if (model.kit.data.templates.length > 50) {
// resolve our promise
deferred.resolve(model);
} else {
// Otherwise reject our promise
deferred.reject();
}
// Return our promise
return deferred.promise;
}]
}
}).state('designer.save', {
url: '/save',
templateUrl: '/app/designer/save.tpl.html',
data: {
pageTitle: 'Save your kit',
requireLogin: true
}
});
I admit the resolves are rather large, but I will find a way to make them smaller.
On a side note, because I am using resolve I can inject it into my controller without having to call the service again, i.e.:
.controller('DesignerController', ['$stateParams', 'model', function ($stateParams, model) {
var self = this,
slug = $stateParams.sport;
// Kit model
self.model = model;
}])
note: that the model is inject after all other dependencies. That makes a difference.