Using Angular require on input to enable signup: require input's/ validation - javascript

I have two input's(checkboxes). One is for a student and the other is for consultant. I want to require at least one or the other input checkboxes. I got them to switch if one is clicked. I just can't figure out how to get it to run inline with the rest of the form validation.
Student:
<input type="checkbox" class="userTypeClass" checked="checked" id="studentCheckbox" name="studentCheckbox" ng-true-value="1" ng-model="user.userType" ng-change="inputCheck(user)"/>
Consultant:
<input type="checkbox" class="userTypeClass" id="consultantCheckBox" name="consultantCheckBox" ng-true-value="2" ng-model="user.userType" ng-change="inputCheck(user)"/>
Signup Button:
<button class="col button-green" ng-disabled="signupForm.$invalid && !flag" ng-click="submit(user)">Continue</button>
JS Controller function:
$scope.inputCheck = function(user) {
var flag = false;
if (user.userType == false) {
flag = true;
} else {
flag = false;
}
console.log(flag);
};

There may be a better answer but here's an idea-
<input type="checkbox" class="userTypeClass" checked="checked" id="studentCheckbox" name="studentCheckbox" ng-true-value="1" ng-model="user.userType" ng-change="inputCheck(user)"/>
<input type="checkbox" class="userTypeClass" id="consultantCheckBox" name="consultantCheckBox" ng-true-value="2" ng-model="user.userType" ng-change="inputCheck(user)"/>
<input type="hidden" required ng-model="user.userType"/>
With the hidden input you're insuring at least one is checked. I don't know the purpose of your inputCheck method but here is a way it could be cleaned up-
$scope.inputCheck = function(user) {
var flag = user.userType === false;
console.log(flag);
};
// or if you dont need to store the flag:
$scope.inputCheck = function(user) {
console.log(user.userType === false);
};
Edit:
Hmm I didn't know false wouldn't work. You could try a hidden checkbox-
(untested, not sure if this will work)
<input type="checkbox" ng-hide="true" required ng-model="user.userType"/>
Or you can unset the value in inputCheck but it's a bit clunky.
$scope.inputCheck = function(user) {
if(user.userType === false) {
user.userType = undefined;
}
};

Related

.checked always returns true?

I'm using vanilla js, and I'm stumped because there's very little code here, so I'm not sure where the problem lies. It may be a misunderstanding on my part on how the attribute works.
function changeState() {
const self = event.target
const parent = event.path[1]
if (self.type == "radio") {
console.log(self.id + " is " + self.checked)
}
}
<div id="usernames_buttons">
<input type="radio" name="usernames" id="usernames-bl" onclick="changeState()" checked>
<label for="usernames-bl">BL</label>
</input>
<input type="radio" name="usernames" id="usernames-wl" onclick="changeState()">
<label for="usernames-wl">WL</label>
</input>
<button data-toggle onclick="changeState()">OFF</button>
</div>
I paired everything down to just this code and ran it in a code pen to test, and the console.log will return true regardless of which option I am clicking. The expectation is that usernames-bl would return true and -wl would return false, but they return true whether the checked attribute is there or not.
You are invoking the changeState() on every click and i guess, as its a radio button, which will always give checked 'true' on click
I think you are doing it right minus the "Off" button should un-check both.. so I added this block:
if (self.type != "radio") {
document.getElementById("usernames-wl").checked = false;
document.getElementById("usernames-bl").checked = false;
}
function changeState() {
const self = event.target
const parent = event.path[1]
if (self.type != "radio") {
document.getElementById("usernames-wl").checked = false;
document.getElementById("usernames-bl").checked = false;
}
console.log("usernames-wl is " + document.getElementById("usernames-wl").checked)
console.log("usernames-bl is " + document.getElementById("usernames-bl").checked)
}
<div id="usernames_buttons">
<input type="radio" name="usernames" id="usernames-bl" onclick="changeState()" checked/>
<label for="usernames-bl">BL</label>
<input type="radio" name="usernames" id="usernames-wl" onclick="changeState()"/>
<label for="usernames-wl">WL</label>
<button data-toggle onclick="changeState()">OFF</button>
</div>

JavaScript Checkbox

I am having troubles with a script with JS, I am still learning but I am stuck for a while.
The solution should be,
IF a checkbox is checked and the value is "" <-- the msgbox should say an message that the textbox should be filled with a value, and so for each checked checkbox, if you uncheck the checkbox, it should dissapear.
Code of 2 checkboxes in html page
<label>
bangkirai
<input id="chk_bangkirai" type="checkbox" onchange="enableTextBox()" />
</label>
<input type="text" id="bangkirai" name="bangkirai" disabled onchange="enableTextBox()" />
<label>
beukenhout
<input id="chk_beukenhout" type="checkbox" />
</label>
<input type="text" id="beukenhout" name="beukenhout" disabled/>
and the JavaScript, I made for each checkbox an other function, but I need to combine the error message in the same msgbox.
function enableTextBox() {
divOutput = document.getElementById("msgbox2");
strValideer = "<ul>";
if (document.getElementById("chk_bangkirai").checked === true) {
document.getElementById("bangkirai").disabled = false;
}
else {
document.getElementById("bangkirai").disabled = true;
}
if (document.getElementById("bangkirai").value === "") {
strValideer += "<li><b>bangkirai: </b>verplicht veld</li>";
}
strValideer += "</ul>";
divOutput.innerHTML = strValideer;
}
function enableTextBox2() {
divOutput = document.getElementById("msgbox2");
strValideer = "<ul>";
if (document.getElementById("chk_beukenhout").checked === true) {
document.getElementById("beukenhout").disabled = false;
}
else {
document.getElementById("beukenhout").disabled = true;
}
if (document.getElementById("beukenhout").value === "") {
strValideer += "<li><b>beukenhout: </b>verplicht veld</li>";
}
strValideer += "</ul>";
divOutput.innerHTML = strValideer;
}
I should probably use an array or an for each itteration ... but I can only find examples with forms ...
I will keep looking for a solution myself, but I hope I can get some inspiration here by experienced coders.
Thanks in advance
You could simplify this a lot and make it more... Concise and less dependent on which checkbox you have. We will do this with an external script and no onClick attributes on our HTML. This will enable us to separate our logic code from our design code. I will also use a placeholder instead of value, as it will create issues when people need to start entering a value (aka, you need to only have the text there when theres no value etc...) It just makes it more complicated.
Since we are dealing with numbers ('stuks' or amounts), lets also only allow number values to be inserted. Lastly, I have not bothered to replicate your HTML as I think the simplified example will make it easier to understand. Update I have also added the required and disabled sattributes here, settings your input to required when the checkbox is checked and disabled when not.
Check the below snippet for comments on the steps taken to do this:
// First, let select all fieldsets like this:
var fieldsets = document.querySelectorAll( 'fieldset.checkbox-message' );
// Lets loop through them
for( let i = 0; i < fieldsets.length; i++ ){
// Lets create variables to store our fieldset, checkbox and input for later use.
let fieldset = fieldsets[ i ];
let checkbox = fieldset.querySelector( 'input[type="checkbox"]' );
let input = fieldset.querySelector( 'input[type="number"]' );
// Lets also store the message we put in placeholder
// We will also give it a default value,
// in case you forget to set the placeholder.
let message = input.placeholder || 'Please fill in the amount';
// Now lets define a function that will fill the placeholder
// based on the checked value of the checkbox
// We will be storing it in a variable because of the scope of a `for` block.
// If you would use function setState() it might be defined globally
// So multiply checkboxes would not work.
let setState = function(){
if( checkbox.checked ){
input.placeholder = message;
input.disabled = false;
input.required = true;
} else {
input.placeholder = '';
input.disabled = true;
input.required = false;
}
}
// Now lets listen for changes to the checkbox and call our setState
checkbox.addEventListener( 'change', setState );
// Lrts also call setState once to initialise the correct placeholder
// for our input element to get started. This will remove any placeholders
// if the checkboxes are unchecked.
setState();
}
<fieldset class="checkbox-message">
<label for="bangkirai">Bangkirai</label>
<input type="checkbox" id="bangkirai" />
<input type="number" placeholder="Tell us, how many 'bangkirai'?" />
<span>stuks</span>
</fieldset>
<fieldset class="checkbox-message">
<label for="beukenhout">Beukenhout</label>
<input type="checkbox" id="beukenhout" />
<input type="number" placeholder="How many 'beukenhout'?" />
<span>stuks</span>
</fieldset>
Good luck coding!
#somethinghere's answer is concise but if we modify your answer as it is you could check this
function enableTextBox() {
bangkirai_validation = document.getElementById("bangkirai_validation");
if (document.getElementById("chk_bangkirai").checked === true) {
document.getElementById("bangkirai").disabled = false;
}
else {
document.getElementById("bangkirai").disabled = true;
bangkirai_validation.style.display='none';
return;
}
if (document.getElementById("bangkirai").value =="") {
bangkirai_validation.style.display='block';
}else
{
bangkirai_validation.style.display='none';
}
}
function enableTextBox2() {
beukenhout_validation = document.getElementById("beukenhout_validation");
if (document.getElementById("chk_beukenhout").checked === true) {
document.getElementById("beukenhout").disabled = false;
}
else {
document.getElementById("beukenhout").disabled = true;
beukenhout_validation.style.display='none';
return;
}
if (document.getElementById("beukenhout").value == "") {
beukenhout_validation.style.display='block';
}else
{
beukenhout_validation.style.display='none';
}
}
<fieldset>
<legend>Bestel gegevens</legend>
<div class="container">
<div class="row">
<div class="span7 id=" houtsoorten"">
<div class="control-group">
<label class="control-label">
bangkirai
<input id="chk_bangkirai" type="checkbox"
onchange="enableTextBox()" >
</label>
<div class="controls">
<div class="input-append">
<input class="inpbox input-mini"
type="number" id="bangkirai" name="bangkirai" placeholder="aantal" disabled
onkeyup="enableTextBox()" onchange="enableTextBox()">
<span class="add-on">stuks</span>
<div style="display:none;" id="bangkirai_validation">Please enter a value</div>
</div>
</div>
</div>
<div class="control-group">
<label class="control-label">
beukenhout
<input id="chk_beukenhout" type="checkbox" onchange="enableTextBox2()" >
</label>
<div class="controls">
<div class="input-append">
<input class="inpbox input-mini"
type="number" id="beukenhout" name="beukenhout" placeholder="aantal"
disabled onkeyup="enableTextBox2()" onchange="enableTextBox2()" >
<span class="add-on">stuks</span>
<div style="display:none;" id="beukenhout_validation">Please enter a value</div>
</div>
</div>
</div>

Make invalid form immediately after loading

I have a simple form written in AngularJS.
I would like to make the form invalid immediately after loading. Unfortunately $scope.myForm.$valid = false; doesn't want work. Do you have any other technique to do it? It is important for me as I want to let user click the button only when he/she choose at least on checkbox. Now you can submit the form always after loading the form.
<form name="myForm" ng-submit="myForm.$valid">
<input type="checkbox" ng-model="obj.first" ng-change="onChange()" /> First <br />
<input type="checkbox" ng-model="obj.second" ng-change="onChange()"/>Second <br />
<input type="checkbox" ng-model="obj.third" ng-change="onChange()"/> Third <br>
<button type="submit" ng-disabled="!myForm.$valid" ng-click="click()">test</button> <br>
</form>
$scope.myForm = {};
$scope.myForm.$valid = false;
$scope.click=function () {
console.log('-------------2', $scope.myForm);
};
$scope.onChange=function () {
console.log('before:', $scope.myForm);
var isValid = false;
angular.forEach($scope.obj, function(value, key) {
if(value == true){
isValid=true;
}
console.log(key + ': ' + value);
});
if(!isValid){
$scope.myForm.$valid = false;
$scope.myForm.$error.checkBoxes = {
isChecked: false
};
}
console.log('after:', $scope.myForm);
}
So this is my final solution, the form in the scope has a function called $setValidity() where we can change the validity state, and notify the form. Refer here, so I check if any of the checkboxes are having true value, then I set the value for one checkbox alone as true, if not then one of the checkboxes with name one is set to $valid = false, thus the entire form will be invalid, please go through my code for the implementation of the solution!
JSFiddle Demo
JS:
var app = angular.module('myApp', []);
app.controller('MyController', function MyController($scope) {
$scope.onChange = function() {
if ($scope.obj) {
if ($scope.obj.first || $scope.obj.second || $scope.obj.third) {
$scope.myForm.one.$setValidity("Atleast one checkbox needs to be selected", true);
} else {
$scope.myForm.one.$setValidity("Atleast one checkbox needs to be selected", false);
}
} else {
$scope.myForm.one.$setValidity("Atleast one checkbox needs to be selected", false);
}
}
});
Try this in your submit button. hope it works
data-ng-disabled="myForm.$submitted || myForm.$invalid && !myForm.$pristine"

Optimizing js -Saving values from checkboxes in object

i'm rather new to js and i'd like to optimize my code.
I have a group of checkboxes and their boolean values are saved in an object for further calculations.
HTML:
<fieldset>
<input type="checkbox" id="checkbox1" onchange="checkbox1Changed()" value="checkbox1">
<input type="checkbox" id="checkbox2" onchange="checkbox2Changed()" value="checkbox2">
<input type="checkbox" id="checkbox3" onchange="checkbox3Changed()" value="checkbox3">
</fieldset>
JS:
//store values for further computation
var boxValues = {
box1: false,
box2: false,
box3: false,
}
//get checkboxvalues from view
var checkbox1 = document.getElementById("checkbox1");
var checkbox2 = document.getElementById("checkbox2");
var checkbox3 = document.getElementById("checkbox3");
//update values in boxValues
function checkbox1Changed() {
if (checkbox1.checked) {
boxValues.box1 = true;
} else {
boxValues.box1 = false;
}
}
function checkbox2Changed() {
if (checkbox2.checked) {
boxValues.box2 = true;
} else {
boxValues.box2 = false;
}
}
function checkbox3Changed() {
if (checkbox3.checked) {
boxValues.box3 = true;
} else {
boxValues.box3 = false;
}
}
Since i plan on having approximately 20 checkboxes in the view there would be a lot of repeating code.
Does anyone know a smarter way to do that?
Thanks in advance!
Vin
Add common class to all the checkboxes
Create an object for the values of all checkboxes
Bind event handler on the checkboxes using the common class
Update the status of clicked checkbox in event handler
Also, it is good practice to bind events in javascript instead of inline in the HTML.
var myObj = {
checkbox1: false,
checkbox2: false,
checkbox3: false
};
$('.myCheckbox').on('change', function() {
var thisId = $(this).attr('id');
myObj[thisId] = this.checked;
console.log(myObj);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.0/jquery.min.js"></script>
<fieldset>
<input type="checkbox" id="checkbox1" value="checkbox1" class="myCheckbox">
<input type="checkbox" id="checkbox2" value="checkbox2" class="myCheckbox">
<input type="checkbox" id="checkbox3" value="checkbox3" class="myCheckbox">
</fieldset>
You can bind the same function to every checkbox, and use the id of the checkbox as the key in your object:
function onCheckBoxChanged(e){
var sender = e.target;
boxValues[sender.id] = (sender.checked);
}
Playing around with this should save you a lot of typing :)

AngularJS input checkbox model?

I have this HTML:
<div>
<input type="checkbox" ng-model="EmailToUser" />
<input type="checkbox" ng-model="EmailToOwner" />
</div>
And this in my controller.js:
$scope.EmailToUser = true;
$scope.EmailToOwner = false;
$scope.Save = function() {
if($scope.EmailToUser) {
alert("I'm supposed to email the user.");
}
if($scope.EmailToOwner) {
alert("I'm supposed to email the owner.");
}
}
This doesn't work, when I click the checkbox the values true/false are constant for some reason. EmailToUser is always true and EmailToOwner is always false regardless of the checkbox state.
But, if I change the code to this:
<div>
<input type="checkbox" ng-model="EmailToUser.Value" />
<input type="checkbox" ng-model="EmailToOwner.Value" />
</div>
And controller.js:
$scope.EmailToUser = {};
$scope.EmailToUser.Value = true;
$scope.EmailToOwner = {};
$scope.EmailToOwner.Value = false;
$scope.Save = function() {
if($scope.EmailToUser.Value == true) {
alert("I'm supposed to email the user.");
}
if($scope.EmailToOwner.Value == true) {
alert("I'm supposed to email the owner.");
}
}
It works. Why? I can't seem to figure the differences between #1 and #2.
Am I not creating new objects the same way inside the scope and assigning a true/false value in both ways?
controller.js(code)
$scope.EmailToUser = true;
$scope.EmailToOwner = false;
$scope.save1 = function(EmailToUser,EmailToOwner){
if($scope.EmailToUser) {
alert("I'm supposed to email the user.");
}if($scope.EmailToOwner) {
alert("I'm supposed to email the owner.");
}
};
controller.html
<div>
<input type="checkbox" ng-model="EmailToUser" />
<input type="checkbox" ng-model="EmailToOwner" />
</div>
<button type="button" ng-click="save1(EmailToUser,EmailToOwner)">click</button>
This code works for me.There is some scope issue.

Categories