I have a rails application which use AngularJS and I have a problem with a form, the problem is that I want to use a checkbox to send values true or false, but it only send true if it's checked and false if it's checked and unchecked after that, but if the user doesn't touch the checkbox, then it's not even sent as parameter.
<div class="checkbox">
<label>
<input type="checkbox" ng-model="car"> Do you have a car?
</label>
</div>
What can I do to make it send false if it the user doesn't ever check it?
Edit: The entire form is this, BTW, the form it's about creating a Poll, the car thing was just an example...
<h1>Create Poll</h1>
<form ng-submit="addPoll()" style="margin-top:30px;">
<div class="form-group">
<label>Title</label>
<input type="text" class="form-control" ng-model="title"></input>
</div>
<div class="form-group">
<label>Description</label>
<textarea type="text" class="form-control" ng-model="description"></textarea>
</div>
<br>
<div class="checkbox">
<label>
<input type="checkbox" ng-model="allow_anonymous_answer" ng-false-value="false"> Allow anonymous answers
</label>
</div>
<br>
<div class="form-group">
<label>Welcome message</label>
<textarea type="text" class="form-control" ng-model="initial_message"></textarea>
</div>
<div class="form-group">
<label>Outgoing Message</label>
<textarea type="text" class="form-control" ng-model="final_message"></textarea>
</div>
<button type="submit" class="btn btn-primary" style="float: right;">Continue</button>
</form>
When you hit Continue I make HTTP POST request with Restangular to create a Poll, but the problem is that when I don't touch the checkbox this is what I see in the log of Rails...
Started POST "/polls.json" for 127.0.0.1 at 2016-01-26 14:05:57 -0300
Processing by PollsController#create as JSON
Parameters: {"title"=>"asddddddddddddddda", "description"=>"aaaaaaaaaaaaaaaaaaaaa", "initial_message"=>"asdasdddddddddd", "final_message"=>"aaaaaaaaaaaaaaaaaaad", "poll"=>{"title"=>"asddddddddddddddda", "description"=>"aaaaaaaaaaaaaaaaaaaaa", "initial_message"=>"asdasdddddddddd", "final_message"=>"aaaaaaaaaaaaaaaaaaad"}}
Note that the parameter allow_anonymous_answer doesn't even appear, if I check the checkbox then I can see that the parameter is set as true, if I check it and then uncheck it, then it's set as false, but the problem is when the user doesn't even touch this, when this happens then the parameter is not even shown...
Just in case you wanna see, this is the controller of AngularJS...
angular.module('myapp').controller('CreatePollCtrl', ['$scope', 'Restangular',
function($scope, Restangular) {
Restangular.setFullResponse(true);
$scope.addPoll = function() {
var poll = {title: $scope.title, description: $scope.description, allow_anonymous_answer: $scope.allow_anonymous_answer, initial_message: $scope.initial_message, final_message: $scope.final_message};
Restangular.all('polls').post(poll).then(function(response) {
});
};
}]);
I think you should put a variable in your controller to achieve the binding between your HTML component and your JS code.
I am currently developing an Angular app, and what i do is to initialize all the ng-model variables in the first lines of my controller, so why dont you give a try to this:
In your first controllers lines:
$scope.allow_anonymous_answer = false;
Did you take a look at angular docs: https://docs.angularjs.org/api/ng/input/input[checkbox]
You can explicitly state what value the checkbox should send when it is not selected using ng-false-value
Add an ng-click to that checkbox and update the model there. Works fine.
<div class="checkbox">
<label>
<input type="checkbox" ng-model="car" ng-click="updateCar(this)">Do you have a car?</input>
</label>
</div>
In your controller:
var updateCar = function(checkbox) {
if (checkbox.checked) {
car = false;
}
else {
car = true;
}
}
I solved it...
In the controller
if ($scope.allow_anonymous_answer == null)
$scope.allow_anonymous_answer = false
Related
I need to be able to see in the Angular controller if the datepicker is pristine or not. Tried all sorts of things including sending the pristine value in a method but cannot get this value. Below is the view code:
<form name="myForm">
<!-- Datepicker From -->
<div class="small-6 medium-5 large-2 columns" ng-if="vm.subViewActive">
<div class="input-group">
<input name="valuationDatePickerFrom" ng-model="name" type="text" class="datepicker" id="valuationDatePickerFrom" placeholder="DD/MM/YYYY" pikaday="vm.datePickerFrom" on-select="vm.selectStartDate(pikaday)" year-range="{{ vm.yearRange }}" >
<div class="input-group-addon">
<label for="valuationDatePickerFrom" class="postfix">
<i class="fa fa-calendar"></i> From
</label>
</div>
</div>
</div>
</form>
and then I also tried :
var isPristine = $scope.myForm.valuationDatePickerFrom.$pristine;
console.log(isPristine);
in my controller but cannot get the pristine value. Read lots of posts here but mainly to do with CSS classes and front-end control or setting the pristine state from the backend not getting or checking the pristine state.
Thanks anybody that can help.
You are using:
var isPristine = $scope.myForm.valuationDatePickerFrom.$pristine;
but your form's name is not myForm.
Change <input name="name"... <input name="valuationDatePickerFrom"...
Then you can use:
var isPristine = $scope.userForm.valuationDatePickerFrom.$pristine;
Also, the controller is getting called before the view is created, so no myForm exists at the time the controller runs. Try adding a $timeout like so:
$timeout(function() {
var isPristine = $scope.userForm.valuationDatePickerFrom.$pristine;
console.log(isPristine);
}, 100);
plunkr
The above solution only works on page load, but you need to know this value when the page is being used. Instead pass the value to the controller when an action happens:
<form name="myForm">
<input type="text" name="valuationDatePickerFrom" ng-model="valuationDatePicker" ng-blur="alerty(myForm.$pristine)">
</form>
.controller('MainController', function($scope) {
$scope.alerty = function(isPristine){
alert('isPristine: ' + isPristine);
};
https://plnkr.co/edit/f0EWvYmoXCn8UOH3QCfE?p=preview
This is my form my HTML
<form id = "myform" name="myform" ng-submit="saveForm()" novalidate >
<div class="input-group">
<span class="input-group-addon"> <img src="/icon.png" alt=""/> </span>
<input type="text" class="form-control" id="username" name="username" ng-model="username" placeholder="Username" autofocus required>
</div>
<span ng-show="formInvalid">Please enter username</span>
<button type="submit" class="btn btn-default" id="saveBtn"> Save </button>
</form>
And inside the controller I have
$scope.formInvalid = false;
$scope.saveForm = function(){
if($scope.myform.username.$invalid){
$scope.formInvalid = true;
}
if($scope.myform.$valid){
//....save it....
At first the form has no error message, if I hit "Save" the "Please enter username" appears, so far, all good.
But if I click on the form field to type a username, the error message does not go away. Even if I finish typing and click somewhere else, the error message still does not go away.
I also try
if(!$scope.myform.username.$valid){
$scope.formInvalid = true;
}
and I also try together
if(!$scope.myform.username.$valid){
$scope.formInvalid = true;
}
if($scope.myform.username.$valid){
$scope.formInvalid = false;
}
and the problem is still there. How can I debug? How do I fix this?
Thanks
You don't have to introduce and maintain a new variable ($scope.formInvalid) for managing the state of your form. Angular maintains the valid / invalid state of the form for you.
As your form is named myform, just show the message about the username based on the value of myform.username.$invalid, and save the form only if myform.$valid is true:
HTML
<span ng-show="myform.username.$invalid">Please enter username</span>
JS
$scope.saveForm = function () {
if ($scope.myform.$valid) {
// save the form
}
};
See fiddle
you can try a watch event,
$scope.$watch('myform.$valid', function(n, o) {
if(n) {
$scope.formInvalid = false;
} else {
$scope.formInvalid = true;
}
});
But i might even be a better idea, if you start using validators.
you do not trigger a change to form invalid property anywhere, I suggest you solve this issue with angulars built in validators and ng-messages module, which will listen to changes on you're form inputs and notify when the inputs are valid or invalid and notify the warning text.
Another approach you can take is use the ng-change directive on the inputs you want to listen to changes in and trigger and update on the form invalid property according to the inputs validity.
example : (taken from the official angular website )
<form name="myForm">
<label>
Enter your name:
<input type="text"
name="myName"
ng-model="name"
ng-minlength="5"
ng-maxlength="20"
required />
</label>
<pre>myForm.myName.$error = {{ myForm.myName.$error | json }}</pre>
<div ng-messages="myForm.myName.$error" style="color:maroon" role="alert">
<div ng-message="required">You did not enter a field</div>
<div ng-message="minlength">Your field is too short</div>
<div ng-message="maxlength">Your field is too long</div>
</div>
</form>
i think this is the most elegant way to do it.
http://plnkr.co/edit/2UFfaG?p=preview
I used this sample code to build a simple app and I noticed that the edit function doesn't work when you are using ng-models that are repeated in a loop. I know this, because I tried using ng-models outside of the ng-repeat loop and it worked perfectly. So when you have two instances of ng-models with the same name, you get a blank data back when you try to get the values back from the view.
This is my view:
<ul ng-repeat="notes in notes">
<li>
<span ng-hide="editing" ng-click="editing = true">{{note.name}} | {{note.content}}</span>
<form ng-show="editing" ng-submit="editing = false">
<label>Name:</label>
<input type="text" ng-model="name" placeholder="Name" ng-required/>
<label>Content:</label>
<input type="date" ng-model="content" placeholder="Content" ng-required/>
<br/>
<button class="btn" ng-click="edit(note.id)">Save</button>
</form>
</li>
</ul>
This is my edit method:
$scope.edit = function (id) {
var note = notesRef.child(id);
var newNote= {
name : $scope.name,
content : $scope.content
}
};
note.update(newNote);
};
When I refer to a ng-model inside of ng-repeat, I can only get the value null for some reason. I get the correct value when I refer to ng-models outside of the ng-repeat for some reason.
How do we solve this problem? What's the simplest solution?
The problem is that the item belongs to the scope of the repeat.
If you changed your ng-model to:
<ul ng-repeat="notes in notes">
<li>
<span ng-hide="editing" ng-click="editing = true">{{note.name}} | {{note.content}}</span>
<form ng-show="editing" ng-submit="editing = false">
<label>Name:</label>
<input type="text" ng-model="note.name" placeholder="Name" ng-required/>
<label>Content:</label>
<input type="date" ng-model="note.content" placeholder="Content" ng-required/>
<br/>
<button class="btn" ng-click="edit(note)">Save</button>
</form>
</li>
</ul>
Where it's now note.name / note.content.
Then instead of padding the note.id to the edit button, you pass in the entire note i.e ng-click="edit(note)"
Then your controller will get passed the entire note.
$scope.edit = function (note) {
// send note to server via $http, changes to `note` are already made directly to the note itself
};
Hope that makes sense.
it should be like this. As we know ng-repeats directive create their own new scope.
bday.editing
<ul ng-repeat="bday in bdays">
<li>
<span ng-hide="bday.editing" ng-click="bday.editing = true">{{bday.name}} | {{bday.date}}</span>
<form ng-show="bday.editing" ng-submit="bday.editing = false">
<label>Name:</label>
<input type="text" **ng-model="bday.name"** placeholder="Name" ng-required/>
<label>Date:</label>
<input type="date" **ng-model="bday.date"** placeholder="Date" ng-required/>
<br/>
<button class="btn" type="submit">Save</button>
</form>
</li>
</ul>
and here what I understand from your question is that you want to edit only the item on which you have click. this is the solution for the same.
One more solution for the same problem is that create a new function that take one argument that is "bday". make edit true only for this item and set editing false for all others element. this solution is for that case if user doesn't submit the form and click on other item.
I'm simply trying to reset a form using the angular functions $setPristine & $setUntouched (several forms are created with ng-repeat).
I assign the form name dynamically by using the syntax {{ someName }} (the name is build on the server side and is passed as json (string)).
The name of the form is correctly assigned in the markup and validations are working as expected. The problem arrises when I pass that name as a parameter in the ng-click="reset(someName)" function.
When debugging the name comes as a string and not as the form object which causes the error. I did a quick test by hard-coding the name and pass that same name and it works fine.
My assumption is, the name coming from json is a string and the type is forwarded to the function as is, instead of the object.
So the question is: is there a way to convert that name so it is interpretated correctly by the controller. Or maybe there is something else I'm missing...
Here is the markup ( notice the name of the form uses {{ resto.contactForm }} ):
<form novalidate name="{{ resto.contactForm }}" ng-submit="submit(restoContact, resto.contactForm.$valid)" class="sky-form">
<div class="form-group">
<label class="checkbox state-success">
<input type="checkbox" ng-model="restoContact.sameAsUser" name="sameAsUser" id="sameAsUser" value="true" ng-click="contactAutoFill()"><i></i>Contact name is same as current user.
<input type="hidden" name="sameAsUser" value="false" />
</label>
</div>
<div class="form-group">
<label class="control-label" for="contactName">Contact Name</label>
<input type="text" ng-model="restoContact.contactName" name="contactName" id="contactName" placeholder="John, Doe" class="form-control" required />
<div ng-show="{{ resto.contactForm }}.contactName.$error.required && !{{ resto.contactForm }}.contactName.$pristine" class="note note-error">Please enter a name or check the box 'Same as current user'.</div>
</div>
<div class="form-group">
<label class="control-label" for="contactPhoneNumber">Contact Phone Number</label>
<input type="text" ng-model="restoContact.contactPhoneNumber" name="contactPhoneNumber" id="contactPhoneNumber" placeholder="+1 555-1234-567" class="form-control" required ng-pattern="phoneNumberPattern" />
<div ng-show="({{ resto.contactForm }}.contactPhoneNumber.$error.required || {{ resto.contactForm }}.contactPhoneNumber.$error.pattern) && !{{ resto.contactForm }}.contactPhoneNumber.$pristine" class="note note-error">Please enter a valid phone number.</div>
</div>
<div class="margin-leftM19">
<button class="btn btn-primary">Save Changes </button>
<button class="btn btn-default" ng-click="reset(resto.contactForm)">Cancel </button>
</div>
</form>
Here is the reset function in the controller (form comes as "contactForm1" which is the correct name but is a string and not the object):
$scope.reset = function (form) {
if (form) {
form.$setPristine();
form.$setUntouched();
}
//$scope.user = angular.copy($scope.master);
};
I have not implemented th submit method but I'm sure I will be running into the same issue.
Any suggestions or advices are welcome.
Thanks in advance...
Here is the fidle.js. the variable data is an exact response from the server.
[http://jsfiddle.net/bouchepat/v0mtbxep/]
SOLUTION:
http://jsfiddle.net/bouchepat/v0mtbxep/3/
I removed $setUntouched as it throws an error.
You can't dynamically name a <form> or <ng-form>.
Although what you want, is make the form usable in the controller. You could do the following:
// in controller
$scope.form = {};
$scope.reset = function() {
$scope.form.contact.$setPristine();
$scope.form.contact.$setUntouched();
};
// in html
<form name="form.contact">
This is happening because resto.contactForm is a string defined on the scope. The angular directive for form is just creating a variable on the scope with the same name. To get the variable by a string, use $eval. This should work:
$scope.reset = function (formName) {
var form = $scope.$eval(formName);
if (form) {
form.$setPristine();
form.$setUntouched();
}
//$scope.user = angular.copy($scope.master);
};
I'm new to Angular and I have a simple retrieve password form with 1 email field and a submit button. I want to clear the form after the form has been submitted, but I can't seem to do it even after following tutorials/answers online.
I think it might be something I'm not understanding fundamentally, so if you could please let me know that would be great.
I'm using Angular v1.2.22
HTML (signin.forgotpassword.html)
<form name="forgotPasswordForm" class="form" role="form" ng-submit="forgetPasswordSubmit(forgetForm.email)" novalidate >
<div>
<label for="input-email" class="col-sm-2 control-label">Email</label>
<div>
<input name="email" ng-model="forgetForm.email" type="email" class="form-control" id="input-email" />
</div>
</div>
<div class="form-group">
<div>
<button name="submit" type="submit">Reset Password</button>
</div>
</div>
</form>
Angular (AuthController)
var forgetPasswordClear = function(){
var defaultForm = {
email: ''
};
// clear input
$scope.forgetForm = defaultForm; // Doesn't clear
// set form as pristine
$scope.forgotPasswordForm.$setPristine(); // Get Cannot read property '$setPristine' of undefined
};
$scope.forgetPasswordSubmit = function(email){
forgetPasswordClear();
};
----------EDIT----------
I'm not sure if it's because my form is sitting in a different ui view? My structure looks something like this:
HTML
<section data-ng-controller="AuthController">
<div data-ui-view>
Some content in there originally
<a ui-sref="signin.forgetpassword">Click here to get password</a>
</div>
</section>
Ui router
.state('signin.forgotpassword', {
url: '/signup/forgot-password',
templateUrl: 'modules/core/templates/signin.forgotpassword.html'
})
You set the wrong model:
Your model is 'forgetForm'
<input name="email" ng-model="forgetForm.email" type="email" class="form-control" id="input-email" ng-pattern="/.+\#.+\..+/" autofocus required />
current:
$scope.forget = defaultForm;
should be:
$scope.forgetForm = defaultForm;
EDIT TO ADDRESS NEW PROBLEM
It's because this is a child scope.
You need to use event emitters and listeners.
$broadcast -- dispatches the event downwards to all child scopes,
$emit -- dispatches the event upwards through the scope hierarchy.
Read more here: Working with $scope.$emit and $scope.$on