Accessing scope in ngRoute - angularjs

I have a simple 1-page app design with two inputs in a static sidebar and an ng-view in which I load JSON data via a $http request in the controller. I'm using ngRoute to load different templates into the view.
This is sample code for my controller:
someModule.controller('JobPostingsCtrl', function($scope, $http) {
$scope.cityFilter = function() {
$http.get("dir/"+$scope.locationFilter+".json")
.then(function(res){
$scope.jobs = res.data;
});
};
$scope.searchFilter = function (jobposting) {
var keyword = new RegExp($scope.keyword, 'i');
return !$scope.keyword || keyword.test(jobposting.title);
};
$scope.locationFilter = $scope.locationFilter || 'all';
$http.get("dir/"+$scope.locationFilter+".json")
.then(function(res){
$scope.jobs = res.data;
});
});
In my index.html I mark up the sidebar with the input fields that are models for locationFilter and keyword:
<input type="search" name="search" id="search" ng-model="keyword">
<input type="search" name="location" id="location" ng-model="locationFilter">
<button id="go" ng-click="cityFilter();">Click</button>
On load, the view displays the 'all' data normally and the searchFilter (based on the keyword model) works on the scope as intended.
However, when I click the cityFilter() button, the controller does get new data (if I do console.log($scope.jobs) inside my cityFilter() function, I see the intended JSON object in my console) but the view does not reflect these changes.
Why does the view reflect the changes in the keyword model, but not the cityFilter() changes? If the scope is different, as I first thought, shouldn't both be ineffective?
I set it up this way because I want the sidebar to be accessible from anywhere in the application. I am mostly confused by the fact that my controller seems to be aware of the changes to $scope variables but doesn't 'transmit' them to the view, even though ng-click is inside an $apply according to Angular documentation. Any idea of what I'm doing wrong?
EDIT: The way my initial template is loaded using routeProvider:
angular.module('someModule', ['ngRoute']).config(['$routeProvider', '$locationProvider',
function($routeProvider) {
$routeProvider
.when('/', {
templateUrl: 'dir/views/job-posting.html',
controller: 'JobPostingsCtrl'
})
...
The HTML for the template:
<div ng-repeat="job in jobs | filter:searchFilter>
{{ job.someProperty }}
</div>
The index.html:
<div ng-controller="MasterCtrl">
<div id="sidebar" ng-controller="JobPostingsCtrl">
<input type="search" name="search" id="search" ng-model="keyword">
<input type="search" name="location" id="location" ng-model="locationFilter">
<button id="go" ng-click="cityFilter();">Click</button>
</div>
<div ng-view></div>
</div>

Related

ng-model not working in ui-router nested view

I have the following code structure
index.html
<body ng-app="jobPortalApp" ng-controller="mainController">
<div ui-view></div>
</body>
then following is my homepage.html template
<div id=header>
</div>
<div ui-view>
<input type="text" ng-model="test">Test</input>
<input type="submit" ng-click="signup()">
</div>
<footer>
</footer>
my angular module file is as follows
var jobPortalApp = angular.module('jobPortalApp',['ui.router']);
jobPortalApp.config(function($stateProvider, $urlRouterProvider){
$urlRouterProvider
.otherwise('/');
$stateProvider
.state('home',
{
url:'/',
templateUrl: './templates/homepage.html',
controller: 'controllerHome'
})
}).controller('mainController', function(){});
following is my home controller
jobPortalApp.controller('controllerHome',function($scope, $http) {
$scope.test="";
$scope.signup = function() {
console.log($scope.test);
}
});
Required:
I want the changed value of test in my controllerHome after the user clicks on signup
Problem:
console.log outputs blank and if I remove $scope.test="";then outputs undefined. I want the changed value of test in my controller.
You usually shouldn't bind directly to $scope due to issues with prototypal inheritance. When trying to read a value from a child scope, if the value doesn't exist you end up reading from the parent scope. But as soon as you write, you write to the child scope. Does it work if you bind to an object instead?
$scope.data = {
test: ""
};
<input type="text" ng-model="data.test">Test</input>
As an alternative, you may also want to look at the controllerAs option for your route:
controllerAs: "ctrl"
Then in your controller:
this.test = "";
And in your template:
<input type="text" ng-model="ctrl.test">Test</input>

select option isn't adding object in ionic

I'm trying to add a mongoose object to another mongoose object using a select bar in a form. All the other key,value pairs insert correctly, even the checkbox bool, but the select-option combo won't save the I've done this before with no problem, but in ionic, it doesn't seem to want to work. Is there a work around or am I just messing something up in the code?
$scope.addProperty = function(prop){
console.log(prop);
Props.add(prop)
.then(function(res) {
console.log(res.data);
//window.location.reload();
})
.catch(function(error){
console.log(error);
});
};
<form method = "post" class="form-inline" role="form" action = "localhost:3000/managers/newApt">
<div class="form-group">
<label class="sr-only" >Tenants:</label>
<select ng-model="prop.tenants" class="column medium-3" ng-options="manager.name for manager in allManagers"> </select>
</div>
<div class="form-group">
<label class="sr-only">Address</label>
<input type="text" class="form-control" ng-model='prop.address'>
</div>
<button type="submit" class="btn btn-default" ng-click='addProperty(prop)'>Add Property</button>
</form>
try to use this video tutorial they use var controllerName = this, inside controller and reference methods and properties of the controller through var controllerName, for example this is a controller:
angular
.module('your-app-module')
.controller('ExampleController', function ($scope, $state) {
//This var is to bind methods and vars in view(html) to this specific controller
var ExmpleCtrl = this; //this is the var that is going to replace $scope
//NOTICE no $scope but rather ExmpleCtrl
ExmpleCtrl.goToState = function (state) {
$state.go(state);
};
});
Now in your html try:
<ion-view ng-controller="ExampleController as exmpleCtrl">
<ion-content>
<!-- notice how I use exmpleCtrl instead of $scope to access controller or to pass info -->
<div ng-click="exmpleCtrl.doSomething()">
</ion-view>
If you still have doubt check this short video (ignore it's for webstorm the way they bind the controller to the a variable inside controller referenced to this is what is useful): http://blog.jetbrains.com/webstorm/2014/03/angularjs-workflow-in-webstorm/

Select some data and then persist to next controller/view in Angularjs

I am bringing in some simple data via a service that uses angular-resource like so:
angular.module('InvoiceService',
['ngResource'])
.factory('InvoiceService', function ($resource) {
return $resource('data.json');
})
.controller("DashboardListCtrl", function (InvoiceService) {
var vm = this;
InvoiceService.query(function (data) {
vm.invoices = data;
});
vm.submit = function (form) {
console.log(form)
};
});
And the html:
<form name="invoices" role="form" novalidate>
<ul>
<li ng-repeat="invoice in vm.invoices">
<input type="checkbox" id="{{'id-' + $index}}" />
<p><strong>Order:</strong></p>
<p>{{invoice.order}}</p>
</li>
<input type="submit" value="Continue" ng-click="vm.submit(invoices)" />
</ul>
</form>
Everything works fine; the data is displays in the view as expected.
The question:
What I'd like to do is be able to select a checkbox, grab the bit of data associated with that checkbox, and pass it along to the next controller/view on submit. How can I do this?
So, what do I do next? Am I on the right track?
**EDIT: added all angular code to help clarify
Posting answer as reply too big to be useful.
You should be using $scope to isolate the controller's data from the rest of the page.
Read up about ng-model http://docs.angularjs.org/api/ng/directive/ngModel and how to use it to two-way-bind checkbox value to a controller variable. No need to use theFormName if you call $scope.submit = function() { } as your ng-model variable will be available in $scope already.
angular.module('InvoiceService',
['ngResource'])
.factory('InvoiceService', function ($resource) {
return $resource('data.json');
})
.controller("DashboardListCtrl", function ($scope, InvoiceService) {
InvoiceService.query(function (data) {
$scope.invoices = data;
});
$scope.submit = function () {
// FIXME to access a property of each $scope.invoices
console.log('checkbox1=' + $scope.invoices[0].checkbox1);
};
});
Then the HTML:
<form role="form" novalidate ng-controller="DashboardListCtrl"><!-- EDIT: added ng-controller=, remove name= -->
<ul>
<li ng-repeat="invoice in invoices"><!-- EDIT: remove 'vm.' -->
<input type="checkbox" id="{{'id-' + $index}}" ng-model="invoice.checkbox1" /><!-- EDIT: added ng-model= -->
<p><strong>Order:</strong></p>
<p>{{invoice.order}}</p>
</li>
<input type="submit" value="Continue" ng-click="submit()" /><!-- EDIT: remove 'vm.' -->
</ul>
</form>

Very simple ng-model watch not working

Here is the jsfiddle.
http://jsfiddle.net/CLcfC/
code
var app = angular.module('app',['']);
app.controller('TestCtrl',function($scope){
$scope.text = 'Change Me';
$scope.$watch('text',function(){
alert('Changed !');
});
})
HTML
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.0.7/angular.min.js"></script>
<div ng-app="app">
<div ng-controller="TestCtrl">
<input type="text" ng-model='text'/>
<span>{{text}}</span>
</div>
</div>
I am not able to see the change in $scope.text. Please help.
This is so easy but what am I missing?
Change the module creation to this, make sure you don't put a empty string in the []. (Obvious the empty string is not a module that can be injected.)
var app = angular.module('app', []);
Demo: http://jsfiddle.net/MWa66/
Your JavaScript file loads after the AngularJS initialization and that's why it fails to find your module. In order to fix it change the initialization to a manual initialization.
First change your HTML and remove the ng-app directive:
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.0.7/angular.min.js"></script>
<div id="appRoot">
<div ng-controller="TestCtrl">
<input type="text" ng-model='text'/>
<span>{{text}}</span>
</div>
</div>
Then go to your JavaScript and use angular.bootstrap method to manually attach your module:
var app = angular.module('app',[]);
app.controller('TestCtrl',function($scope){
$scope.text = 'Change Me';
$scope.$watch('text',function(){
alert('Changed !');
});
});
angular.element(document).ready(function() {
angular.bootstrap(document.getElementById('appRoot'), ['app']);
});
You can find more help on manual AngularJS initialization here.
Thank you! I solved this annoying thing!
The solution that worked for me was that I use angular UI router and there I had used the following code
.state('app.monimes', {
url: "/monimes",
views: {
'menuContent' :{
templateUrl: "templates/monimes.html",
controller: 'sampleCtrl'
}
}
})
so then in the controller I had
/***
*
*Controller for tests..
*/
.controller('sampleCtrl',['$scope','sampleService', function($scope, $sampleService) {
$scope.username="em";
// Watch for changes on the username property.
// If there is a change, run the function
$scope.$watch('username', function(newUsername) {
// uses the $http service to call the GitHub API
// //log it
$scope.log(newUsername);
// and returns the resulting promise
$sampleService.events(newUsername)
.success(function(data, status, headers) {
// the success function wraps the response in data
// so we need to call data.data to fetch the raw data
$scope.events = data.data;
});
},true);
}
]);
and in the view I had
<div>
<label for="username">Type in a GitHub username</label>
<input type="text" ng-model="username" placeholder="Enter a GitHub username, like a user" />
<pre ng-show="username">{{ events }}</pre>
</div>
but that didn't work.
so I added ng-controller="sampleCtrl"
to the div and now it works :D
so that means that the view is loaded after the controller loads and the watcher doesn't get added to the watching variable.

nest ng-view inside a form

given the controller
function ctl($scope, $http) {
$scope.postForm = function() {
console.log("submitting form")
}
}
and the view
<form name="pform" ng-show="!error.Show">
<div ng-view></div>
<button type='button' value='Save' ng-click="postForm()" />
</form>
The controller method postForm doesn't get called, however, if i move the form tag into the view the method is called. Is there a reason that this doesn't work as I expect it to? Is there another way to accomplish the goal of sharing the form controls across different views?
Update
my module and routeProvider are configured like this:
angular.module("profilemodule", [])
.config(['$routeProvider', function ($routeProvider) {
$routeProvider
.when("/info", { templateUrl: '/partials/profile/info.html', controller: ProfileController })
.when("/user", { templateUrl: '/partials/profile/user.html', controller: ProfileController })
.when("/introduction", { templateUrl: '/partials/profile/editor.html', controller: ProfileController })
.otherwise({ redirectTo: '/info' });
}]).run(function ($rootScope, $location) {
$rootScope.location = $location;
})
and the page includes some nav elements which are set based on the location service like so:
<div class="row">
<div class="offset2 span10">
<ul class="nav nav-pills">
<li ng-class="{active: location.$$path.substring(0, '/info'.length) == '/info'}"><a href="#/info" >Information</a></li>
<li ng-class="{active: location.$$path.substring(0, '/user'.length) == '/user'}"><a href="#/user" >User</a></li>
<li ng-class="{active: location.$$path.substring(0, '/intro'.length) == '/intro'}"><a href="#/intro" >Introduction</a></li>
</ul>
</div>
</div>
<form name="pform" method="POST" ng-show="!error.Show">
<div ng-view></div>
<button type='button' value='Save' ng-click="postForm()" />
</form>
the ng-class statements works perfectly, is it because I've set the location property of $scope in the module's run method?
thanks,
jason
ng-view with routing creates a new scope with the controller, and you can't reach a child scope. Your submit action lies in the parent scope and the form data lies in the child scope (created by ng-view).
If you want to use common form controls, you can use ng-include, this directive gets template it and renders that in the current scope.
Move your form controls to a new template, then include them in all of your forms.
API reference:
http://docs.angularjs.org/api/ng.directive:ngInclude

Resources