I' trying out firebase 3 with my Ionic app. (I just made one to mess with - so I figure i might as well do everything right from the beginning, such as using ControllerAs notation)
everything in the controller works fine. just the logUserOut method doesnt fire - at all! I'm at a loss.
controller:
.controller('DashCtrl', function($scope, $ionicModal, DataService, AuthService) {
var ctrl = this;
ctrl.icons = [];
//// SERVICE GETS
ctrl.allIcons = DataService.icons();
ctrl.pages = DataService.pages();
////
//// FILTER INFORMATION
ctrl.loadIcons = function() {
console.log(ctrl.pages)
for (icon in ctrl.allIcons) {
var i = ctrl.allIcons[icon];
// console.log(i)
if(i.active){
ctrl.icons.push(i);
}
}
};
////
//// ACTIONS
ctrl.logUserOut = function(){
console.log('this is not being called')
// AuthService.logout();
};
////
});
html:
<ion-modal-view>
<ion-pane >
<ion-content scroll="false" >
<section class = "modal-container">
<div class="item modal-header">
<button class="button button-left button-icon light ion-android-close" ng-click="ctrl.closeProfileModal()"></button>
<div class="light text-center">
<button class="button button-clear" ng-click="controller.closeProfileModal()">
<img class="avatar-modal" src="img/mike.png">
</button>
</div>
</div>
<div class = "row modal-profile-row">
<div class = "col">
<button class="button button-clear">
<span class="title light">Personal Info</span>
</button>
</div>
</div>
<div class = "row modal-profile-row">
<div class = "col">
<button class="button button-clear" ng-click="ctrl.logUserOut()">
<span class="title light">Sign Out</span>
</button>
</div>
</div>
</section>
</ion-content>
</ion-pane>
</ion-modal-view>
app.js:
.state('tab.dash', {
url: '/dash',
views: {
'tab-dash': {
templateUrl: 'templates/tab-dash.html',
controller: 'DashCtrl',
controllerAs: 'ctrl'
}
}
})
EDIT:
It turns out the problem was with Sublime Text : for some reason, there was a weird cache issue - I was editing the file but the changes weren't recognized. I'm Glad that I asked because now I am using 'controllerAs:' in the $stateProvider and not 'controller: someController as something'. Thank you all for your help!
In your app.js change to:
.state('tab.dash', {
url: '/dash',
views: {
'tab-dash': {
templateUrl: 'templates/tab-dash.html',
controller: 'DashCtrl',
controllerAs: 'ctrl' // <-- here
}
}
})
I'll explain a little more. In your controller you set a variable to 'this'. The name you use can be anything such as wowItsAVariable = this; however when you attach your controller you can use a completely different name such as controllerAs: 'wowSomeOtherName' and that is how you reference it in your html. The name doesn't matter and I would stay away from using names such as 'controller' as that doesn't tell anyone what controller you're trying to reference. Hope that helps.
Related
I am trying to get the value of $stateParams in my controller but it is always undefined but I can see there is a value in my view.
As you can see there are values on each link.
app.js
.state('app.help', {
url: '/help',
views: {
'menuContent': {
templateUrl: 'templates/help.html'
}
}
})
.state('app.help-replies', {
url: '/help/:id',
views: {
'menuContent': {
templateUrl: 'templates/help-replies.html'
}
}
})
html view
this is the where the lists of data displays
<div ng-repeat="x in helpData">
<a class="row responsive-xs" href="#/app/help/{{x.id}}">
<div class="col"><h6>{{x.subject}}</h6></div>
</a>
</div>
this is where the single view of the clicked data in the above view.
<div class="row responsive-xs" ng-init="viewHelpAndReplies()">
<div class="col">
<h5>Subject: {{$scope.help_id}}</h5>
</div>
</div>
controller.js
$scope.viewHelpAndReplies = function(){
console.log($stateParams.id);
}
I think you should use ui-sref to pass data
<div ng-repeat="x in helpData">
<a class="row responsive-xs" ui-sref="app.help-replies({id: x.id})">
<div class="col"><h6>{{x.subject}}</h6></div>
</a>
</div>
and retrieve id with
$scope.id = $stateParams.id;
Okay I think I got what I needed. But I am not sure if this is good, but for me it is okay because it works.
Here's what I do:
I change the href
href="#/app/help/{{x.id}}"
into ng-click and create a function
ng-click="doViewHelp({id:x.id})"
and create function in my controller.js:
$scope.doViewHelp = function(data){
$state.go('app.help-replies');
// some codes...
}
Thanks.
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);
So I have no idea what is wrong, but im assuming i have a loop running in the background of my code or that im routing incorrectly. But all i know is when i try to go to my index page, my entire browser is taken down, no errors or anything, just crashing. Any help would really be appreciated im just trying to move on from this problem.And in case this changes anything i am using a rails backend.
planoxApp.config(['$stateProvider','$urlRouterProvider',
function($stateProvider, $urlRouterProvider) {
$stateProvider
.state('home', {
url: '/',
templateUrl: 'templates/home/nav.html',
authenticate: true
})
.state('home.index', { // our home page
url: '/index',
views: {
"": {templateUrl: 'templates/home/home.html'},
"assembly#index": { templateUrl: "templates/home/assembly.html" },
"client#index": { templateUrl: "templates/home/client.html" },
"photoplan#index": { templateUrl: "templates/home/home_photoplan.html" }
},
authenticate: true
})
Here is the main routes causing problems, the home one is just a nav bar, and when you go to the home tab its supposed to take you to the index page, but no dice. Im not sure how much of my controller i should show, but here a small part.Its the parts that directly effect the routes.
app.run(function ($rootScope,$location, $localStorage){
$localStorage.recent = ""
$rootScope.$on('$routeChangeSuccess', function() {
console.log("working")
recent.push($location.$$path);
});
});
app.run(function ($rootScope, $state, AuthService) {
$rootScope.$on("$stateChangeStart", function(event, toState, toParams, fromState, fromParams){
if (toState.authenticate && !AuthService.isAuthenticated()){
// User isn’t authenticated
console.log(AuthService.isAuthenticated())
$state.transitionTo("login");
event.preventDefault();
}
});
});
// GET request Area
$http.get('client.JSON').success(function(data){
$scope.clients = data;
});
$http.get('photoplan.JSON').success(function(data){
$scope.photoplans = data;
$scope.complete = true;
// if(main.photoplans.plano_order_status === "Complete"){
// console.log()
// $scope.complete = true;
// }else{
// $scope.complete = false;
// }
});
$http.get('assembly.JSON').success(function(data){
// main.assemblys = $filter('filter')(data, function(d){return d.employee_id == mainid});
$scope.assemblys = data;
console.log($scope.assemblys)
});
$http.get('employee.JSON').success(function(data){
$scope.employees = data;
});
}]);
This is the index page, and one of the nested views it has, all the views look roughly the same.
<div class="container" ng-controller="MainCtrl">
<!-- Main Section -->
<div class="home no-subheader container">
<div class="row" >
<!-- left -->
<section name="assembly-queue" class="molding col-md-4" id="assembly">
<div class="gutter" >
<div ui-view="assembly"> </div>
</div>
</section>
<!-- <section name="employee-queue" ng-if="type === 'admin'" class="molding col-md-4" id="employee">
<div class="gutter" id="scrollArea">
<div ui-view=".employee"></div>
</div>
</section> -->
<!-- middle -->
<section name="clients" class="molding col-md-4" id="clients">
<div class="gutter" >
<div ui-view="client"> </div>
</div>
</section>
<!-- right -->
<section name="photoplans" class="molding col-md-4" id="photoplans">
<div class="gutter" >
<div ui-view="photoplan"> </div>
</div>
</section>
</div>
</div>
</div>
This is the assembly page.
<div id="expanding" >
<div class="top row">
<h2> Assembly Queue</h2>
<form class="navbar-form navbar-left default" role="search">
<div class="form-group">
<input type="text" ng-model="searchassembly" class="form-control query" placeholder="Search Assembly Queue">
</div>
</form>
</div>
</div>
<article class="assembly snippet row" ng-repeat="assembly in assemblys|filter:searchassembly" >
<div class="left col-xs-7" >
<address>{{assembly.address_part1}},{{assembly.address_part2}}</address>
<p class="timeline-data"> Due on {{assembly.date_due}}</p>
<p class="timeline-data"> Job Type: {{assembly.job_type}}</p>
<p class="timeline-data"> Delivery Type: {{assembly.delivery_type}}</p>
</div>
<div class="right col-xs-5 text-center">
<div class="corner-ribbon" ng-click="open(assembly.id)" > </div>
<button ng-if="assembly.new_order" class="btn btn-default" ui-sref="photoplans({ id : assembly.photoplan_id })" ><span class="fa fa-pencil-square-o" aria-hidden="true"></span></button>
<button ng-if="assembly.new_order === false" class="btn btn-default" ui-sref="assign({address : assembly.address, realtor: assembly.realtor})" ><span class="fa fa-external-link" aria-hidden="true"></span></button>
</div>
</article>
If anyone has had similar issues or can see red flags in this please let me know, i am really stuck on this issue.
Okay so i actually found the answer myself, and im leaving the solution here for future people who might have this issue. But basically i need to have word of some kind in my home route, so instead of just /, i need /home. Because the browser was trying to load this #//index, and that was causing crashes. When using rails and angular together, make sure to have named routes to prevent this problem. Also make sure your nested views look like this, whatever#parent.child. Heres my new code.
planoxApp.config(['$stateProvider','$urlRouterProvider',
function($stateProvider, $urlRouterProvider) {
$stateProvider
.state('home', {
url: '/home',
templateUrl: 'templates/home/nav.html',
authenticate: true
})
.state('home.index', { // our home page
url: '/index',
views: {
"": {templateUrl: 'templates/home/home.html'},
"assembly#home.index": { templateUrl: "templates/home/assembly.html" },
"client#home.index": { templateUrl: "templates/home/client.html" },
"photoplan#home.index": { templateUrl: "templates/home/home_photoplan.html" }
},
authenticate: true
})
I can't figure out how to do a multi-state form. The main issue is the form.$errors seem to look at the active state rather then the whole form. In other words, the submit button is meant to be disabled until ALL required questions are answered for the entire form, but it seems to become enabled when all the required questions are answered for the active state.
Here's a simplified Plunker: http://plnkr.co/edit/O49eO4uRlUjoWHlxV6Li?p=preview
And below is my actual code.
View:
<div class="row">
<div class="col-md-4">
<ul class="nav nav-pills nav-stacked">
<li role="presentation" ng-repeat="section in vm.sections[0].sections" ng-if="section.fields">
<a ui-sref="subject.items.new.section({sectionUrl: section.url})">
<span class="badge badge-warning" title="Number of unanswered required questions for {{section.name}}">1</span>
{{section.name}}
</a>
</li>
</ul>
</div>
<div class="col-md-8">
<form class="assessment-item" name="assessmentForm">
<div ui-view></div>
<hr>
<button class="btn btn-primary btn-raised" ng-disabled="assessmentForm.$invalid" ng-click="vm.createCompletedItem()">Save Changes</button>
<button class="btn btn-inverse btn-inverse-danger" back-button>Cancel</button>
</form>
</div>
</div>
Routes:
.state('subject.items.new', {
url: '/items/new/:availableItemUrl',
templateUrl: 'components/items/new.html',
controller: 'ItemNewCtrl',
controllerAs: 'vm',
resolve: {
getAvailableItemsResolve: function(DataService) {
return DataService.availableItems().getList();
},
getUser: function($cmUserData) {
return $cmUserData.getUser(1);
}
}
})
.state('subject.items.new.section', {
url: '/:sectionUrl',
template: '<div class="animated fadeIn"><formly-form model="vm.completedItem.answers" fields="vm.fields"></formly-form></div>',
controller: function($scope, $stateParams, lodash) {
var vm = this;
var _ = lodash;
vm.questions = _.filter($scope.vm.sections[0].sections, { 'url' : $stateParams.sectionUrl });
vm.fields = vm.questions[0].fields;
vm.completedItem = $scope.vm.completedItem;
},
controllerAs: 'vm'
})
itemNewCtrl:
(function() {
'use strict';
angular
.module('casemanagerApp')
.controller('ItemNewCtrl', ItemNewCtrl);
function ItemNewCtrl($stateParams, $filter, DataService, lodash, getUser, getAvailableItemsResolve) {
var vm = this;
var _ = lodash;
vm.item = DataService.completedItems().one();
vm.availableItems = getAvailableItemsResolve;
vm.sections = _.filter(vm.availableItems, { 'url' : $stateParams.availableItemUrl });
vm.completedItem = DataService.completedItems().one();
vm.completedItem.subjectId = $stateParams.subjectId;
vm.completedItem.name = vm.sections[0].name;
vm.completedItem.probationOfficer = getUser.firstName + ' ' + getUser.lastName;
vm.completedItem.label = 'Final';
}
})();
The issue is due to the way you have things set up. When I switch tabs, angular-ui-router removes the view entirely and therefore angular only sees one formly-form, therefore only one formly-form is validated at a time. I would recommend against using angular-ui-router and instead just use a directive (like angular-ui-bootstrap's tabset directive) which uses ng-show to keep both forms on the page at a time and therefore both will be taken into account when doing validation. Here's an example that might help you there.
All you need to do is set a flag, like "formComplete" in the model and then flip it on once they get to the last question...we have similar issues at work with something like this and that's how we work around it.
Alternatively you could simply move the submit button to the last page
I have this page which links the input.countNum scope variable to the input with ng-model. The value which is displayed on the button shows fine. When you click the button on the first page, it navigates to the second page which also displays the scope variable. But the variable is reset to the default declaration value in the controller code.
How do I maintain the scope value from ng-model between pages within the same controller?
tab-dash.html
<ion-view view-title="Test">
<ion-content class="padding">
<div class="list">
<label class="item item-input">
<span class="input-label">Count</span>
<input class="text-right" type="number" pattern="[0-9]*" ng-model="input.countNum">
</label>
</div>
<button class="button button-full button-positive" ng-click="create()" ui-sref="tab.count">
Count is ({{input.countNum}})
</button>
</ion-content>
</ion-view>
controller.js
.controller('DashCtrl', function($scope) {
$scope.input = {
countNum: 1
};
$scope.create = function() {
// Logic here
};
})
count.html
<ion-view view-title="Count">
<ion-nav-bar class="bar-energized">
<ion-nav-back-button class="button-clear">
<i class="ion-arrow-left-c"></i> Back
</ion-nav-back-button>
</ion-nav-bar>
<ion-content class="padding">
<button class="button button-full button-positive">
({{input.countNum}})
</button>
</ion-content>
</ion-view>
app.js
.state('tab', {
url: "/tab",
abstract: true,
templateUrl: "templates/tabs.html"
})
// Each tab has its own nav history stack:
.state('tab.dash', {
url: '/dash',
views: {
'tab-dash': {
templateUrl: 'templates/tab-dash.html',
controller: 'DashCtrl'
}
}
})
.state('tab.count', {
url: '/count',
views: {
'tab-dash': {
templateUrl: 'templates/count.html',
controller: 'DashCtrl'
}
}
})
Controllers are not shared between pages - a new instance is created each time the controller is used. You should not expect to be able to share data from a controller with anything outside the scope of that controller either. If you need to share data between pages or controllers, you should use a service or "value" object to maintain that state. Another option would be passing the data between the pages using the state params:
ui-sref="tab.count({ input: input })"
Note that Ionic uses the Angular UI Router project for its navigation logic, so the documentation there also applies to using Ionic.