ng-model not working in ui-router nested view - angularjs

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>

Related

angular html 5 form validation breaks when I use ui-sref

I have a multi step angular form using ui.router. I have a form html file that loads each step as a view. Each step has a button with a ui-sref link that takes the user to the next step. However it wont show the html 5 validation hints unless I remove the ui-sref. How can I have the validation work while still triggering the ui-sref at the same time?
my main form view:
<form ng-submit="processForm()" name="mortgage">
<div class="row">
<!-- our nested state views will be injected here -->
<div id="form-views" class="small-12 columns" ui-view></div>
</div>
</form>
my view html:
<h3>Please provide some information about your property</h3>
<label for="name">Zip Code</label>
<input type="text" pattern="[0-9]{5}" class="form-control" name="zipcode" type="number" ng-model="formData.zipcode" placeholder="Zip Code" required>
<button ui-sref="form.verify" type="submit" class="next">Next</button>
my controller
angular
.module('angularApp', [
'rzModule',
'btford.modal'
'ui.router'
])
.config(function ($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise('/form/property-type');
$stateProvider
.state('form', {
url: '/form',
templateUrl: 'views/form.html',
controller: 'FormCtrl'
})
.state('form.info', {
url: '/property-info',
templateUrl: 'views/property-info.html'
})
.state('form.verify', {
url: '/property-verify',
templateUrl: 'views/property-verify.html'
})
.controller('FormCtrl', function($scope) {
$scope.formData = {};
$scope.processForm = function() {
console.log($scope.formData);
};
});

Angular: Why Won't Model Update Outside Of View In Same Controller?

I have found a number of posts talking about models/views not updating, but I still can't figure this out. I'm new to Angular, btw so I suspect this is noob issue.
I have the below Angular app.
When the text input test_var is edited, the edited value isn't updated in the sidebar, but it is in the view. Why and how do I fix it?
This works when I don't use views and routes.
I've tried a sidebar controller, but no difference. I've tried $rootScope, which partially worked (it broke other functionality), but I'd prefer not to use a global scope.
Thanks for taking a look.
HTML
<body>
<div ng-app="rxApp" ng-controller="WizardCtrl">
<div class="ng-view">
</div>
<div class="sidebar">
<span ng-bind="test_var"></span>
</div>
</div>
</body>
View (One.html)
<input ng-model="test_var" />
<span ng-bind="test_var"></span>
Controller
rxApp.controller( 'WizardCtrl', function ( $scope, $http, $routeParams, $location, FileUploader ) {
$scope.test_var = 'please work!';
)};
Routes
rxApp.config(['$routeProvider',
function($routeProvider) {
$routeProvider.
when('/one', {
templateUrl: 'templates/one.html',
controller: 'WizardCtrl'
}).
when('/two', {
templateUrl: 'templates/two.html',
controller: 'WizardCtrl'
}).
otherwise({
redirectTo: '/one'
});
}
]);
Controllers are disposed when transmuting routes.
As for Best Practice you should create a Service to handle that data. You should not use controllers to carry data between views. In your case, the problem is Controllers are disposed when transmuting routes.
See the angular docs on how to use controllers correctly. http://docs.angularjs.org/guide/dev_guide.mvc.understanding_controller
The problem is the making of model variables.
You have to have a dot in model. Make your model point to an object.
So in your controller do like this -
rxApp.controller('WizardCtrl',function($scope, $http, $routeParams,$location, FileUploader){
$scope.test ={
var : 'please work!'
};
)};
View (One.html)
<input ng-model="test.var" />
<span ng-bind="test.var"></span>
HTML
<body>
<div ng-app="rxApp" ng-controller="WizardCtrl">
<div class="ng-view">
</div>
<div class="sidebar">
<span ng-bind="test.var"></span>
</div>
</div>
</body>
To read more about scope go through this UnderStanding Scopes

Why my angular controller donĀ“t find my form - $scope.form undefined

I am trying do understand why my form is not recognize inside the maincontroller, if I put another controller outside, my form is recognize.
config.js
var myApp = angular.module('Myapp', ['ui.router','oc.lazyLoad','ui.bootstrap','kendo.directives','ngStorage',]);
function config($stateProvider, $urlRouterProvider, $ocLazyLoadProvider) {
$urlRouterProvider.otherwise("/index/main");
$stateProvider
.state('testing', {
url: "/testing",
controller: 'MyController',
templateUrl: "testing.html"
});
}
angular
.module('Myapp')
.config(config)
.run(function($rootScope, $state) {
$rootScope.$state = $state;
});
MyController.js
function MyController($scope) {
//do something
$scope.test = {name: 'das'};
$scope.sendTest = function () {
console.log($scope.form.$valid);
console.log($scope.form.testNumber.$valid);
console.log($scope.form.testName.$valid);
};
};
angular
.module('Myapp')
.controller('MyController', ["$scope"]);
testing.html
<form name="form" novalidate>
<p>
<label>Number: </label>
<input type="number" min="0" max="10" ng-model="test.number" name="testNumber" required />
</p>
<p>
<label>Name: </label>
<input type="text" ng-model="test.name" name="testName" required />
</p>
<button ng-click="sendTest()">Submit</button>
</form>
Like this a have this error
TypeError: Cannot read property '$valid' of undefined
but if I create another controller inside MyController.js and i move the code inside like this
function ChildController($scope,$timeout) {
$scope.test = {
name: 'das'
};
$scope.sendTest = function () {
console.log($scope.form.$valid);
console.log($scope.form.testNumber.$valid);
console.log($scope.form.testName.$valid);
};
};
function MyController($scope) { //do other stuff ...};
angular
.module('Myapp')
.controller('ChildController', ["$scope", ChildController])
.controller('MyController', ["$scope"]);
and add the ng-controller to the form like this
<form name="form" novalidate ng-controller='ChildController'>
the form is reconize correctly and working.
Can anyone explain what I am missing here, i would like to understand better, I am a novice.
Thanks you for the help.
Best regards.
Jolynice
As seen in Brad Barber's comment:
The form is being created on the child scope and not the controller
scope.
A good solution like he suggested would be to add the bindToController and controllerAs syntax to your route object:
function config($stateProvider, $urlRouterProvider, $ocLazyLoadProvider) {
$urlRouterProvider.otherwise("/index/main");
$stateProvider
.state('testing', {
url: "/testing",
controller: 'MyController',
controllerAs: 'viewCtrl',
bindToController: 'true',
templateUrl: "testing.html"
});
}
Now you can bind the name of the form as viewCtrl.form:
<form name="viewCtrl.form" novalidate>
<p>
<label>Number: </label>
<input type="number" min="0" max="10" ng-model="viewCtrl.test.number" name="testNumber" required />
</p>
<p>
<label>Name: </label>
<input type="text" ng-model="viewCtrl.test.name" name="testName" required />
</p>
<button ng-click="viewCtrl.sendTest()">Submit</button>
</form>
You can then notate it in your controller using this:
function MyController($scope) {
// Adding variables functions available to ctrl scope
// same as vm = this;
angular.extend(this, {
test: {name: 'das'},
sendTest: function() {
console.log(this.form.$valid);
console.log(this.form.testNumber.$valid);
console.log(this.form.testName.$valid);
}
});
};
angular
.module('Myapp')
.controller('MyController', ["$scope", MyController]);
Here is a codepen that I hacked together for you:
Check whether if the form is inside any div which has ng-if condition
Like
<div ng-if="condition">
<form name="viewCtrl.form">
.
</form>
</div>
If this is so, the form would return undefined since there is new scope created for the DOM containing ng-if condition. Then use ng-show instead of ng-if that would not create new scope. I got this solution from this answer

Angularjs controller is showing undefined?

I am working on node app using angularjs and cassandra.
when i go to page such as register page then front end is coming appropriately but it is showing error that controller is undefined.
Error: error:areq
Bad Argument
this is app.js (main js configuring file)
angular.module('app', ['ui.router'])
.config(['$urlRouterProvider', '$stateProvider',
function($urlRouterProvider, $stateProvider) {
$urlRouterProvider.otherwise('/');
$stateProvider
.state('home', {
url: '/',
templateUrl: '/browser/views/home.html'
})
.state('register', {
url: '/register',
templateUrl: '/browser/views/register.html',
controller: 'RegisterCtrl'
})
.state('login', {
url: '/login',
templateUrl: '/browser/views/login.html',
controller: 'LoginCtrl'
})
}
]);
this is register.html file followed by the path of controller.
<div ng-controller="RegisterCtrl" class="container-fluid">
<div class="row custom-row2">
<div class="col-md-6 col-lg-6 col-sm-6">
<h4 class="sign_up">{{ title }}</h4>
<form class="form-horizontal" id="login_form" name="login_form" role="form">
<div class="form-group">
<label class="control-label col-sm-3" for="name">Name:</label>
<div class="col-sm-9">
<input ng-model="name" type="text" class="form-control" name="field1" id="name" aria-describedby="inputSuccess3Status" placeholder="Enter Your Name....">
</div>
</div>
</form>
</div>
</div>
this is the registerCtrl.js file which is coming on checking in firebug
angular.module('app', ['ui.router'])
.controller('RegisterCtrl', ['$scope',
function($scope, RegiserService) {
$scope.title = "Sign Up";
}
]);
but title which has to come from the registerCtrl controller is not coming and {{ title }} is coming in that place.
i have gone through several times through this but didn't able to get what is going wrong in defining controller.
You are recreating the module again by doing angular.module('app', ['ui.router']).controller. Just use the getter syntax angular.module('app') to get the module once the app has been created. I am assuming you are doing the same while registering the service RegiserService which cleans up anything else registered to the same module app. Once the module has been created by using the syntax angular.module('moduleName', [..dep]) you should just get the module with the getter syntax angular.module('app') while registering any other subsequent entities.
Module creation (Just once):
angular.module(moduleName, [requires], [configFn]);
Module Getter (to access already created module):
angular.module(moduleName);
See documentation
When passed two or more arguments, a new module is created. If passed only one argument, an existing module (the name passed as the first argument to module) is retrieved.
So for example:-
angular.module('app').controller('RegisterCtrl',...
angular.module('app').service('RegiserService',...
Along with redefining module as mentioned by PSL,
One more point is - what is RegiserService? If it is some service then the definition of controller is wrong.
correct definition is
angular.module('app', ['ui.router'])
.controller('RegisterCtrl', ['$scope', 'RegiserService',
function($scope, RegiserService) {
$scope.title = "Sign Up";
}
]);

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