AngularJS: Validators in Controller no binding with HTML side - javascript

All in-line validations in HTML side are working OK, but when I use functions in my Controller (functions ingresarNuevoEmpleador and limpiarNuevoEmpleador), always get $invalid=true. $setPristine neither works.
Apparently both sides are referencing different objects because controller functions
do not modify the state of the html side validators.
<form name="frmEmpleadorDirecto" novalidate>
<div class="row">
<div class="col-xs-8 col-sm-8">
<div class="form-group has-feedback"
ng-class="{'has-error': frmEmpleadorDirecto.nempleador.$invalid && (frmEmpleadorDirecto.nempleador.$touched || frmEmpleadorDirecto.$submitted)}">
<label for="input501">Empleador Directo</label>
<input type="text" class="form-control text-uppercase" name="nempleador" placeholder="Nombre Empleador" ng-model="objEmpleador_.nombreEmpleador_" ng-minlength="2" ng-maxlength="30" ng-required="true">
<span class="help-block" ng-if="frmEmpleadorDirecto.nempleador.$error.minlength && frmEmpleadorDirecto.nempleador.$touched">too short</span>
<span class="help-block" ng-if="frmEmpleadorDirecto.nempleador.$error.maxlength && frmEmpleadorDirecto.nempleador.$touched">too long</span>
<span class="help-block" ng-if="frmEmpleadorDirecto.nempleador.$error.required && frmEmpleadorDirecto.nempleador.$touched">required</span>
</div>
</div>
</div>
<div class="text-right">
<button type="submit" class="btn btn-success btn-mm" ng-disabled="frmEmpleadorDirecto.$pristine || frmEmpleadorDirecto.$invalid" ng-click="ingresarNuevoEmpleador()">Aceptar</button>
<button type="button" class="btn btn-warning btn-mm" ng-click="limpiarNuevoEmpleador()">Limpiar</button>
</div>
</form>
Controller:
angular.module('BlurAdmin.pages.empleador_')
.controller('CtrlEmpleadorNuevo',CtrlEmpleadorNuevo);
function CtrlEmpleadorNuevo($scope,$http,$rootScope) {
$scope.objEmpleador_ = new eva.Empleador_();
$scope.ingresarNuevoEmpleador = function()
{
console.log("Nombre: " + $scope.objEmpleador_.nombreEmpleador_); //OK
if($scope.objEmpleador_.$valid) //always invalid
{
console.log('valid!');
}else {
console.log('invalid!'); }
}
$scope.limpiarNuevoEmpleador = function ()
{
$scope.objEmpleador_.$setPristine; //no changes
$scope.objEmpleador_.nombreEmpleador_ = ''; //Works: reset html field
}
}
Objects:
eva.Empleador_ = function() {
var self = this;
self.nombreEmpleador_ = '';
};

Your form is bound on your $scope and inputs and their validity can be reached following the name attribute.
$scope.ingresarNuevoEmpleador = function(){
console.log("Nombre: " + $scope.objEmpleador_.nombreEmpleador_); //OK
if($scope.frmEmpleadorDirecto.nempleador.$valid) {
console.log('valid!');
}else {
console.log('invalid!');
}
};
Plunker

Related

AngularJS 1.6.8: Unable to submit form and display success message

I have a simple query submission form with name, email and query fields and a component with a controller function having the submit function to submit the form.
I am using ng-submit directive in the <form></form> tag to submit the user input and display a success message on submission.
below is the code for the respective files.
contact.html
<div ngController="contactController as vm">
<div class="heading text-center">
<h1>Contact Us</h1>
</div>
<div>
<form class="needs-validation" id="contactForm" novalidate method="post" name="vm.contactForm" ng-submit="saveform()">
<div class="form-group row">
<label for="validationTooltip01" class="col-sm-2 col-form-label">Name</label>
<div class="input-group">
<input type="text" class="form-control" id="validationTooltipName" placeholder="Name" ng-model="vm.name" required>
<div class="invalid-tooltip">
Please enter your full name.
</div>
</div>
</div>
<div class="form-group row">
<label for="validationTooltipEmail" class="col-sm-2 col-form-label">Email</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text" id="validationTooltipUsernamePrepend">#</span>
</div>
<input type="email" class="form-control" id="validationTooltipEmail" placeholder="Email"
aria-describedby="validationTooltipUsernamePrepend" ng-model="vm.email" required>
<div class="invalid-tooltip">
Please choose a valid email.
</div>
</div>
</div>
<div class="form-group row">
<label for="validationTooltip03" class="col-sm-2 col-form-label">Query</label>
<div class="input-group">
<input type="text" class="form-control" id="validationTooltipQuery" ng-model="vm.query" placeholder="Query" required>
<div class="invalid-tooltip">
Please write your Query.
</div>
</div>
</div>
<div class="btn-group offset-md-5">
<button class="btn btn-primary" type="submit">Submit</button>
<button class="btn btn-default" type="button" id="homebtn" ng-click="navigate ('home')">Home</button>
</div>
</form>
<span data-ng-bind="Message" ng-hide="hideMessage" class="sucessMsg"></span>
</div>
</div>
contact.component.js
angular.module('myApp')
.component('contactComponent', {
restrict: 'E',
$scope:{},
templateUrl:'contact/contact.html',
controller: contactController,
controllerAs: 'vm',
factory:'userService',
$rootscope:{}
});
function contactController($scope, $state,userService,$rootScope) {
var vm = this;
$scope.navigate = function(home){
$state.go(home)
};
$scope.saveform = function(){
$scope.name= vm.name;
$scope.email= vm.email;
$scope.query= vm.email;
$scope.hideMessage = false;
$scope.Message = "Your query has been successfully submitted."
};
$scope.user = userService;
};
//localStorage code
function userService($rootScope) {
var service = {
model: {
name: '',
email: '',
query:''
},
SaveState: function () {
sessionStorage.userService = angular.toJson(service.model);
},
RestoreState: function () {
service.model = angular.fromJson(sessionStorage.userService);
}
}
$rootScope.$on("savestate", service.SaveState);
$rootScope.$on("restorestate", service.RestoreState);
return service;
$rootScope.$on("$routeChangeStart", function (event, next, current) {
if (sessionStorage.restorestate == "true") {
$rootScope.$broadcast('restorestate'); //let everything know we need to restore state
sessionStorage.restorestate = false;
}
});
//let everthing know that we need to save state now.
window.onbeforeunload = function (event) {
$rootScope.$broadcast('savestate');
};
};
UPDATE: On Submit, When I check the response in network tab in dev tools, I do not see the submitted values. All I see is the markup.
In your template, the name of the method is saveform:
ng-submit="saveform()"
But in your controller, it's save:
$scope.save = function() { ... }
Rename it to saveform:
$scope.saveform = function() { ... }

Angular - $scope.myForm.$setPristine() is undefined

Form is not cleared after saved record in angularJs. I'm trying to reset form many ways, but form is not reset.
My angularjs version is 1.4.8.
This question is also a duplicate, but I tried what stack overflow users said. That has not worked for me.
Looking for a positive reply
Thank you.
Html code:
<form name="myForm" id="myForm" novalidate>
<input type="hidden" name="forumValue" ng-model="fid.forumValue"
id="forumValue" placeholder="fourm Id" />
<div class="form-group row">
<label for="inputAnswer" class="col-sm-2 col-form-label">Answer</label>
<div class="col-sm-10">
<textarea rows="10" name="answer" class="form-control"
ng-model="fid.answer" required></textarea>
</div>
</div>
<div class="form-group row">
<div class="col-sm-2"></div>
<div class="col-sm-8">
<button type="button" class="btn btn-success"
ng-click="saveUserAnswer(fid)">Post Your Answer</button>
</div>
</div>
</form>
Controller Code:
$scope.saveUserAnswer = function(fid) {
UserRepository.saveUserAnswer(fid).then(
function(response) {
var status = response.message;
if (status == "success") {
alert("posted success");
$scope.UserAnswer=getUserOnIdAnswer(fid.UserValue);
$scope.myForm.$setPristine();
$scope.myForm.$setUntouched();
$state.go('UserAnswer');
}
else {
$scope.User=response;
alert("posted Fail,Please correct the details..!!");
}
});
};
Is your form wrapped in an ng-if statement? If so, the form might be inside a child scope, and you might try:
Option A
Replace your ng-if with an ng-hide.
Option B
Bind the form to an existing object on the parent scope:
$scope.myData = {};
$scope.saveUserAnswer = function(fid) {
...
};
Then in your HTML, refer to the form on the parent scope:
<form name="myData.myForm" id="myForm" novalidate>
</form>
Source: https://github.com/angular/angular.js/issues/15615
I have attempted to recreate your problem but without the call to the UserRepository just to confirm that we can set the form $pristine value to true and to reset the form.
<form name="form.myForm" id="myForm" novalidate>
<input type="hidden" name="forumValue" ng-model="fid.forumValue" id="forumValue" placeholder="fourm Id" />
<div class="form-grou`enter code here`p row">
<label for="inputAnswer" class="col-sm-2 col-form-label">Answer</label>
<div class="col-sm-10">
<textarea rows="10" name="form.myForm.answer" class="form-control" ng-model="fid.answer" required></textarea>
</div>
</div>
<div class="form-group row">
<div class="col-sm-2"></div>
<div class="col-sm-8">
<button type="button" class="btn btn-success" ng-click="saveUserAnswer(fid)">Post Your Answer</button>
</div>
</div>
</form>
<pre>{{form.myForm.$pristine}}</pre>
and the controller code like so :
$scope.form = {};
$scope.saveUserAnswer = function(fid) {
$scope.form.myForm.$setPristine();
$scope.fid = {};
//omitted the user repository code
};
The above will set the pristine value of the form to true and also reset the value of fid on click of the button.
EDIT
Also the call to your repository function should be in this format:
UserRepository.saveUserAnswer(fid).then(
function(response){
//success
},
function(response){
//error
}
);
In controller try to add '$scope.fid.answer=null;' after scope.myForm.$setPristine();
like this.
$scope.saveUserAnswer = function(fid) {
UserRepository.saveUserAnswer(fid).then(
function(response) {
var status = response.message;
if (status == "success") {
alert("posted success");
$scope.UserAnswer=getUserOnIdAnswer(fid.UserValue);
$scope.myForm.$setPristine();
$scope.myForm.$setUntouched();
$scope.fid.answer=null;
$state.go('UserAnswer');
}
else {
$scope.User=response;
alert("posted Fail,Please correct the details..!!");
}
});
};

ng-form inside ng-repeat with submit button outside of ng-repeat

I've this code:
<div class="row" ng-repeat="input in inputs | filter:inputNumber">
<ng-form name="form1">
<div class="col-xs-3">
<div class="form-group">
<input ng-model="inputs.number[$index]" type="number" name="number$index" class="form-control" placeholder="" min="1" max="9999" required />
<small class="label label-danger" data-ng-show="submitted && form1.number$index.$error.required">required</small>
<small class="label label-danger" data-ng-show="submitted && form1.number$index.$error.number">number</small>
<small class="label label-danger" data-ng-show="submitted && form1.number$index.$error.max">number max</small>
</div>
</div>
</ng-form>
</div>
<button data-ng-click="add(form1)" class="btn-add" style="padding-left: 40%;"></button>
Controller:
// Form add handler.
$scope.add = function(form) {
// Trigger validation flag.
$scope.submitted = true;
// If form is invalid, return and let AngularJS show validation errors.
if (form.$invalid) {
console.log('invalid');
return;
} else {
var newItemNo = $scope.inputs.length + 1;
var inputs = { 'id': 'input' + newItemNo }
$scope.inputs.push(inputs);
$scope.isDisabled = false;
}
};
The problem is I can only validate the form inputs inside ng-repeat and ng-form, and I need to trigger the event outside of that html block, maybe I'm just being noob (first time using angular1 validations). I will appreciate some help. Thanks in advance.
Based on you comment and following the same goal of generating a form for each element in your ng-repeat, this should be the answer:
html
<form name="generalForm"> <!-- this form will be valid if all sub-forms are valid-->
<div class="row" ng-repeat="input in inputs | filter:inputNumber">
<ng-form name="form1">
<div class="col-xs-3">
<div class="form-group">
<input ng-model="inputs.number[$index]" type="number" name="number$index" class="form-control" placeholder="" min="1" max="9999" required />
<small class="label label-danger" data-ng-show="submitted && form1.number$index.$error.required">required</small>
<small class="label label-danger" data-ng-show="submitted && form1.number$index.$error.number">number</small>
<small class="label label-danger" data-ng-show="submitted && form1.number$index.$error.max">number max</small>
</div>
</div>
</ng-form>
</div>
<button data-ng-click="add(generalForm)" class="btn-add" style="padding-left: 40%;"></button>
</form>
controller
// Form add handler.
$scope.add = function(form) {
// Trigger validation flag.
$scope.submitted = true;
// If form is invalid, return and let AngularJS show validation errors.
if (form.$invalid) {
console.log('invalid');
return;
} else {
var newItemNo = $scope.inputs.length + 1;
var inputs = { 'id': 'input' + newItemNo }
$scope.inputs.push(inputs);
$scope.isDisabled = false;
}
};

Call function on 'Enter' press

Here is my HTML code:
<div class="panel-footer">
<div class="input-group">
<input id="btn-input" class="form-control input-sm chat_input message" type="text" placeholder="Write your message here..." ng-model="messageToSend">
<span class="input-group-btn">
<button id="btn_chat" class="btn btn-primary btn-sm btn_chat" value="79">Send</button>
</span>
</div>
</div>
And here is my jQuery code:
$('.message').keypress(function (e) {
if (e.which == 13) {
var msg = $(this).val();
var id = $(this).closest('span').next('button.btn_chat').val();
alert(id+" "+msg);
sendMessage(msg,id);
}
e.preventDefault();
});
Here is my send message function:
var sendMessage = function(messageToSend,id) {
// $log.debug(messageToSend);
id = parseInt(id);
if(messageToSend.length != 0){
$http.post('/chat/send/',{message:messageToSend,chat_room_id:id}).then(function (response) {
$log.debug(response.data);
$('input.message').val("");
});
}
};
Now I want to call my sendMessge function in it, when enter button press after message written.
But when I press enter button my jQuery not run. How can I solve this problem?
Angular provides mechanism, You can create a form and use ngSubmit to bind function to execute when form is submitted.
So, when Enter is pressed form will be submitted.
HTML
<div class="panel-footer">
<div class="input-group">
<form ng-submit="sendMessage(messageToSend, 79)">
<input id="btn-input" class="form-control input-sm chat_input message" type="text" placeholder="Write your message here..." ng-model="messageToSend" />
<span class="input-group-btn">
<button id="btn_chat" class="btn btn-primary btn-sm btn_chat" value="79">Send</button>
</span>
</form>
</div>
</div>
Add method in your controller
$scope.sendMessage = function(messageToSend,id) {
// $log.debug(messageToSend);
id = parseInt(id);
if(messageToSend.length != 0){
$http.post('/chat/send/',{message:messageToSend,chat_room_id:id}).then(function (response) {
$log.debug(response.data);
$('input.message').val("");
});
}
};
If you don't want to use form, then you can use ngKeyup
<input ng-keyup="$event.keyCode == 13 ? sendMessage(messageToSend, 79): null" ng-model="messageToSend" >
You are using the line
var id = $(this).closest('span').prev('button.btn_chat').val();
however, the $(this) in that case is an <input> element, which isn't inside a <span>. Therefore .closest('span') will be returning an empty set.

Can't access form inside AngularJS controller

Can't access form variable from my controller, when i try to access it by $scope.locationForm i've got 'undefined', but when i call console.log($scope) i can see in console there have loactionForm.
My HTML code
<div ng-controller="LocationsController as ctrl">
<form class="form-inline" name="locationForm">
<div class="form-group">
<!-- <div class="input-group"> -->
<label for="location-name">Название населенного пункта</label>
<input required
name="name"
ng-model="ctrl.location.name" type="text" class="form-control" id="location-name" placeholder="Название населенного пункта">
<label for="location-name">Район</label>
<select required
name="region_id"
ng-model="ctrl.location.region_id"
ng-options="region.id as region.name for region in ctrl.regions" class="form-control" placeholder="Название района"></select>
<input ng-click="ctrl.save()"
ng-disabled="locationForm.$invalid" type="submit" class="btn btn-default" value="Cохранить">
<a class="btn btn-default" ng-click="ctrl.reset()" ng-show="locationForm.$dirty">Сброс</a>
<!-- </div> -->
</div>
</form>
My Controller code:
function LocationsController($scope, Location, Region, $q) {
var lc = this,
l_index;
lc.form ={};
lc.regions = lc.locations = [];
lc.regions = Region.query();
lc.regions.$promise.then(function(data) {
lc.locations = Location.query();
});
lc.getRegion = function (id) {
return lc.regions.filter(function(obj) {
return obj.id == id;
})[0].name;
};
console.log($scope);
// console.log($scope.locationForm);
lc.reset = function () {
lc.location = new Location;
}
lc.reset();
};
The problem is when the LocationsController is initialized the form element is not yet compiled. So one possible hack is to use a timeout like
function LocationsController($scope, Location, Region, $q, $timeout) {
//then later
$timeout(function(){lc.reset();})
}

Categories