Angular Checkboxes "Select All" functionality with only one box selected initially - html

I have a form that contains 3 checkboxes: "Select All", "Option 1", and "Option 2".
<form id="selectionForm">
<input type="checkbox" ng-model="selectAll" >Select all
<br>
<input type="checkbox" ng-checked="selectAll" checked>Option 1
<br>
<input type="checkbox" ng-checked="selectAll">Option 2
</form>
On the initial page load I want only Option 1 to be checked. And then if the Select All checkbox gets checked it should automatically check Option 1 and Option 2 so all are selected.
The problem is on the initial page load the ng-checked="selectAll" gets evaluated which overrides my attempt to initially check only Option 1 (selectAll = false initially), so nothing is selected.
This seems like a simple problem to solve, but I can't figure out a solution... Thanks in advance for any insights or advice!

Another way to go about it is to use a model for the options, set default selection in the model and have your controller handle the logic of doing select all.
angular.module("app", []).controller("ctrl", function($scope){
$scope.options = [
{value:'Option1', selected:true},
{value:'Option2', selected:false}
];
$scope.toggleAll = function() {
var toggleStatus = !$scope.isAllSelected;
angular.forEach($scope.options, function(itm){ itm.selected = toggleStatus; });
}
$scope.optionToggled = function(){
$scope.isAllSelected = $scope.options.every(function(itm){ return itm.selected; })
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"> </script>
<div ng-app="app" ng-controller="ctrl">
<form id="selectionForm">
<input type="checkbox" ng-click="toggleAll()" ng-model="isAllSelected">Select all
<br>
<div ng-repeat = "option in options">
<input type="checkbox" ng-model="option.selected" ng-change="optionToggled()">{{option.value}}
</div>
</form>
{{options}}
</div>

Try this:
<form id="selectionForm">
<input type="checkbox" ng-model="selectAll" >Select all
<br>
<input type="checkbox" ng-checked="selectAll || option1" ng-init="option1=true" ng-model="option1">Option 1
<br>
<input type="checkbox" ng-checked="selectAll">Option 2
</form>

I like to use an ng-repeat for clarity on showing what you're selecting/un-selecting, basically you end up with a nice little object to base it all on, and adding to it is just easier.
Here's a Plunker
*Also notice how you can achieve allSelected? with a loop func and not a ton of html, and I'm sure this can be done with less spaghetti but it works *
app.controller('MainCtrl', function($scope) {
$scope.allSelected = false;
$scope.checkboxes = [{label: 'Option 1',checked: true}, {label: 'Option 2'}}}];
$scope.cbChecked = function(){
$scope.allSelected = true;
angular.forEach($scope.checkboxes, function(v, k) {
if(!v.checked){
$scope.allSelected = false;
}
});
}
$scope.toggleAll = function() {
var bool = true;
if ($scope.allSelected) {
bool = false;
}
angular.forEach($scope.checkboxes, function(v, k) {
v.checked = !bool;
$scope.allSelected = !bool;
});
}
});

Related

HTML: password field is not getting cleared

I'm trying to clear an input type password field. I've tried with all the methods such as
1) $('#password').val(' ');
2) setTimeout(function(){ $('#password').val(' ');}, 50);
3) $("input[type='password']").val(' ');
4) $scope.model.password = ' ';
5) document.getElementById('password').value = ' ';
Among these only, the 5th one had cleared my password object, but even then the value was not cleared from the HTML page.
Just wanted to know why is the Screen retaining the password, seems like a cache issue in HTML. But the thing is the model.userName gets cleared in HTML page and not the password field.
This is my HTML code
<div class="modal_sections">
<ul>
<li>
<input type="text" ng-keydown="loginKeydown($event)" ng-model="model.userName"> </li>
<li>
<input type="password" ng-keydown="loginKeydown($event)" ng-model="model.password" placeholder="***********" id="password"> </li>
</ul>
And this is my controller code
var resetPassword = function () {
if (condition) {
$('#password').val('');
setTimeout(function () { $('#password').val(''); }, 50);
$("input[type='password']").val('');
$scope.model.password = '';
document.getElementById("password").value = "";
document.getElementById("password").placeholder = "";
}
}
Can someone help me out on this? I just want to clear the password from HTML page as well.
You have added a space to the password field while resetting remove that. It will work perfectly.
function clearPassword(){
document.getElementById('password').value = '';
}
function checkValue() {
var passwordFieldValue = document.getElementById('password').value;
alert("Value of password field= " + passwordFieldValue);
}
<input type="password" ng-keydown="loginKeydown($event)" ng-model="model.password" class="form-control password" placeholder="*****" id="password" autocomplete="off">
<button onClick="clearPassword()">Clear</button>
<button onClick="checkValue()">Check Value</button>
If you want to completely clear the field then you have to clear the placeholder value as well. I am posting pure js code, if you want to accomplish it in different way you can easily do it. You get the idea
function change() {
var x = document.getElementById("psw").value = "";
var x = document.getElementById("psw").placeholder = "";
}
The running code sample is here https://jsfiddle.net/uj8yyp1d/
Don't work with jQuery, using ng-model works fine. Make sure your $scope.model is defined. You can't reset some property if it's undefined.
var app = angular.module("app",[]);
app.controller("test", function($scope){
$scope.model={};
$scope.model.userName = "abc";
$scope.model.password = "123";
$scope.resetPassword = function () {
$scope.model.userName = "";
$scope.model.password = "";
}
});
<!DOCTYPE html>
<html>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
<body ng-app="app">
<div ng-controller="test" class="modal_sections">
<ul>
<li>
<input type="text" ng-model="model.userName">
</li>
<li>
<input type="password" ng-model="model.password" placeholder="***********" id="password">
</li>
</ul>
<button type="button" ng-click="resetPassword()">Clear</button>
</div>
</body>
</html>
if you want to clear the password field by clicking on some button then use
HTML:
<button ng-click = someFunction()>CLick Me </button>
JS:
someFunction(){
$scope.model.password=null;
}

Multiple <form> tags in different locations with the same target iframe?

I have an iframe in the content area:
<iframe name="my_iframe" frameBorder="0" height="200" src="about:blank"></iframe>
I have a submit-button under it:
<form action="includes/action.php" method="post" target="my_iframe">
<input type="submit" value="Submit">
</form>
And I want some checkboxes in another area:
<form action="includes/action.php" method="post" target="my_iframe">
<input type="checkbox" name="option">
</form>
But it doesn't work, the submit-button works but it doesn't send the checkbox.
I can't put everything in one -tag because I want the checkbox in a sidepanel of the main-view and the submit-button on a page that is in another page. (Loaded per ajax? I'm using frameworks7 btw.)
Is it not possible with different form-tags or is it because of the ajax thingy?
EDIT1: I managed to build an example for easier understanding with plunker, it doesn't work with php and I don't have a webspace right now, but you get the idea.
http://plnkr.co/edit/dfqzCbeQWgg9hAyCpGpb
UPDATE 2
To get a cleaner result without the stale cache confusing tests I have updated it, please review newest update:
http://plnkr.co/edit/34KOyh9rIEGV3bXNsD9F?p=preview
UPDATE
Now that I was provided with a very complete and nicely coded demo, I have solved your problem.
http://plnkr.co/edit/Z2I1Q2swIXmFfynalaLB?p=preview
Note: I'm using a test server, so the cache may be stale. Just change the action by adding a number to the end.
Example
change:
http://www.hashemian.com/tools/form-post-tester.php/so_post_chk
to:
http://www.hashemian.com/tools/form-post-tester.php/so_post_chk1
When the checkbox is checked, your result should be cache=on
When the checkbox is not checked, your result should be cache=
You could assign one or more inputs (usually type="hidden") outside of the forms and collect whatever data from anywhere on the page regardless of which form it originated from.
http://plnkr.co/edit/er5RoJ049xSBwtR7gtTI?p=preview
This demo revolves around a simple JS function:
function toOutput(x) {
var str = x.toString();
var out4 = document.getElementById('out4');
out4.value += str;
}
Note the special condition for checkboxes:
if(this.checked) {
toOutput(this.value);
text1.value += this.value;
};
It's needed because when the click event is triggered on a checkbox, it is considered on every click checked and unchecked. I assume that the checkbox value is collected when it's actually checked.
I got option onsubmit form ...
Try it:
Create test.php file:
<form id="myForm" action="includes/action.php" method="post" target="my_iframe">
<input onclick="myFunction()" type="submit" value="Submit">
</form>
<form action="includes/action.php" method="post" target="my_iframe">
<input id="cbopt" type="checkbox" name="option" value="option" checked="checked">
</form>
<script>
function myFunction() {
var y = document.createElement("input");
y.setAttribute("type", "checkbox");
y.setAttribute("value", "option");
y.setAttribute("name", "option");
y.setAttribute("checked", "checked");
document.getElementById("myForm").appendChild(y);
var x = document.getElementById("cbopt").name;
document.getElementById("demo").innerHTML = x;
var z = document.forms.length;
document.getElementById("demo").innerHTML = z;
}
</script>
Code for includes/action.php :
<iframe name="my_iframe" frameBorder="0" height="150" width="555" src="about:blank">
<p id="demo"></p>
</iframe>
<?php
//$site = $_POST['doorde'];
//$url = $_POST['doordie1'];
$opt = $_POST['option'];
echo $opt;
?>
Try and comment me ...
Here's what you can do, copy the values from one form to the other before submitting, making sure you remove fields added previously when you submit again.
<form action="includes/action.php" method="post" target="my_iframe" id="myform">
<input type="submit" value="Submit">
</form>
<form action="includes/action.php" method="post" target="my_iframe" id="otherform">
<input type="checkbox" name="option">
</form>
<iframe name="my_iframe" frameBorder="0" height="200" src="about:blank"></iframe>
<script>
function copyFormFieldsIntoHiddenFields(from, to) {
var elementsAdded = [];
for (var i = 0; i < from.elements.length; i++) {
var nodeToCopy = from.elements[i];
// Unchecked checkboxes do not get sent to server
if (nodeToCopy.type != "checkbox" || nodeToCopy.checked) {
var hiddenField = document.createElement('input');
hiddenField.type = "hidden";
hiddenField.name = nodeToCopy.name;
hiddenField.value = nodeToCopy.value;
to.appendChild(hiddenField);
elementsAdded.push(hiddenField);
}
}
return elementsAdded;
}
var addedFields = [];
document.getElementById('myForm').addEventListener('submit', function() {
// Remove any fields that were previously added
for (var i = 0; i < addedFields.length; i++) {
this.removeChild(addedFields[i]);
}
// Add the new hidden fields
var copyFrom = document.getElementById('otherform');
addedFields = copyFormFieldsIntoHiddenFields(copyFrom, this);
});
</script>

HTML Form: Other input required ONLY if other is selected

I'm currently working on a form with a bunch of options. On some of the questions, there is an "Other" option for the user to type in whatever they choose. I am trying to make it appear only "Other" is selected (I've gotten this to work on the first question but not the others). I am also trying to make this input required ONLY if they select it, so that they can't submit the form having selected "Other" and left it blank.
Here is my HTML and the Javascript for making the other text inputs appear when selected:
<label for="Accom">Question</label>
<table>
<tr>
<td><select name="Accom">
<option value="">Select...</option>
<option value="Handicapped">Handicap Accessibility</option>
<option value="Hearing Impaired">Hearing Impaired</option>
<option value="Visually Impaired">Visually Impaired</option>
<option value="OtherAccom">Other</option>
</select>
</td>
</tr>
<tr>
<td colspan="4">
<label style="" id="other">If Other, Please Specify
<input type="text" name="Other_Accom" size="20"></label></td><tr></table>
.
window.onload=function() {
var other = document.getElementById('other', 'otherAccom','otherDiet');;
other.style.display = 'none';
document.getElementsByName('Title', 'Diet', 'Accom')[0].onchange = function() {other.style.display =(this.value=='Other')? '' : 'none'};
I'm also trying to get a this to work for a checkbox form.
<label for="Interests">Question</label><br>
<input class="checkbox2" TYPE="checkbox" NAME="formInterests[]" required value="Use Cases ||" />Use Cases<br>
<input class="checkbox2" TYPE="checkbox" NAME="formInterests[]" required value="Other" />Other<br>
<label style="" id="other">If Other, Please Specify
<input type="text" name="Other_Interests" size="20"></label>
Thank you very much!
EDIT 1: When I try and duplicate the function, it stops working for everything.
window.onload=function() {
var other = document.getElementById('other', 'otherAccom', 'otherDiet');;
other.style.display = 'none';
document.getElementsByName('Title')[0].onchange = function() {other.style.display = (this.value=='Other')? '' : 'none'};
};
window.onload=function() {
var otherDiet = document.getElementById('other', 'otherAccom', 'otherDiet');;
otherDiet.style.display = 'none';
document.getElementsByName('Diet')[0].onchange = function() {otherDiet.style.display = (this.value=='OtherDiet')? '' : 'none'};
};
document.getElementsByName('Title', 'Diet', 'Accom')[0].onchange = function() {other.style.display =(this.value=='Other')? '' : 'none'};
This selects an array of elements, which you then access by [0], meaning you target the first element (which will be the first of the three that appears in the DOM), and add the onChange listener to it.
This results, as you said yourself:
(I've gotten this to work on the first question but not the others)
Because you actually only run the code on one of the three elements.
You should instead use something like:
document.getElementsByName('Title', 'Diet', 'Accom').forEach(function(element) {
element.onChange = function() {
var target = document.getElementById('Other'+this.name);
if(this.options[this.selectedIndex].value=='Other') {
target.style.display = 'block';
} else {
target.style.display = 'none';
}
};
});
The basic idea is using a forEach to loop through ALL your desired elements, rather than just one of them.
Keep in mind that:
<option value="OtherAccom">Other</option>
does not have value="Other", but value="OtherAccom". Make sure your javascript and html are consistent with eachother.
you can use IDs only once on a page ("other")
you need to rename those other "others" and create seperate functions for them

Edit In Place Content Editing

When using ng-repeat what is the best way to be able to edit content?
In my ideal situation the added birthday would be a hyperlink, when this is tapped it will show an edit form - just the same as the current add form with an update button.
Live Preview (Plunker)
HTML:
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="utf-8">
<title>Custom Plunker</title>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.0.3/angular.min.js"></script>
<script>
document.write('<base href="' + document.location + '" />');
</script>
<script src="app.js"></script>
<link href="//netdna.bootstrapcdn.com/twitter-bootstrap/2.2.0/css/bootstrap-combined.min.css"
rel="stylesheet">
</head>
<body ng-app="birthdayToDo" ng-controller="main">
<div id="wrap">
<!-- Begin page content -->
<div class="container">
<div class="page-header">
<h1>Birthday Reminders</h1>
</div>
<ul ng-repeat="bday in bdays">
<li>{{bday.name}} | {{bday.date}}</li>
</ul>
<form ng-show="visible" ng-submit="newBirthday()">
<label>Name:</label>
<input type="text" ng-model="bdayname" placeholder="Name" ng-required/>
<label>Date:</label>
<input type="date" ng-model="bdaydate" placeholder="Date" ng-required/>
<br/>
<button class="btn" type="submit">Save</button>
</form>
</div>
<div id="push"></div>
</div>
<div id="footer">
<div class="container">
<a class="btn" ng-click="visible = true"><i class="icon-plus"></i>Add</a>
</div>
</div>
</body>
App.js:
var app = angular.module('birthdayToDo', []);
app.controller('main', function($scope){
// Start as not visible but when button is tapped it will show as true
$scope.visible = false;
// Create the array to hold the list of Birthdays
$scope.bdays = [];
// Create the function to push the data into the "bdays" array
$scope.newBirthday = function(){
$scope.bdays.push({name:$scope.bdayname, date:$scope.bdaydate});
$scope.bdayname = '';
$scope.bdaydate = '';
};
});
You should put the form inside each node and use ng-show and ng-hide to enable and disable editing, respectively. Something like this:
<li>
<span ng-hide="editing" ng-click="editing = true">{{bday.name}} | {{bday.date}}</span>
<form ng-show="editing" ng-submit="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>
The key points here are:
I've changed controls ng-model to the local scope
Added ng-show to form so we can show it while editing
Added a span with a ng-hide to hide the content while editing
Added a ng-click, that could be in any other element, that toggles editing to true
Changed ng-submit to toggle editing to false
Here is your updated Plunker.
I was looking for a inline editing solution and I found a plunker that seemed promising, but it didn't work for me out of the box. After some tinkering with the code I got it working. Kudos to the person who made the initial effort to code this piece.
The example is available here http://plnkr.co/edit/EsW7mV?p=preview
Here goes the code:
app.controller('MainCtrl', function($scope) {
$scope.updateTodo = function(indx) {
console.log(indx);
};
$scope.cancelEdit = function(value) {
console.log('Canceled editing', value);
};
$scope.todos = [
{id:123, title: 'Lord of the things'},
{id:321, title: 'Hoovering heights'},
{id:231, title: 'Watership brown'}
];
});
// On esc event
app.directive('onEsc', function() {
return function(scope, elm, attr) {
elm.bind('keydown', function(e) {
if (e.keyCode === 27) {
scope.$apply(attr.onEsc);
}
});
};
});
// On enter event
app.directive('onEnter', function() {
return function(scope, elm, attr) {
elm.bind('keypress', function(e) {
if (e.keyCode === 13) {
scope.$apply(attr.onEnter);
}
});
};
});
// Inline edit directive
app.directive('inlineEdit', function($timeout) {
return {
scope: {
model: '=inlineEdit',
handleSave: '&onSave',
handleCancel: '&onCancel'
},
link: function(scope, elm, attr) {
var previousValue;
scope.edit = function() {
scope.editMode = true;
previousValue = scope.model;
$timeout(function() {
elm.find('input')[0].focus();
}, 0, false);
};
scope.save = function() {
scope.editMode = false;
scope.handleSave({value: scope.model});
};
scope.cancel = function() {
scope.editMode = false;
scope.model = previousValue;
scope.handleCancel({value: scope.model});
};
},
templateUrl: 'inline-edit.html'
};
});
Directive template:
<div>
<input type="text" on-enter="save()" on-esc="cancel()" ng-model="model" ng-show="editMode">
<button ng-click="cancel()" ng-show="editMode">cancel</button>
<button ng-click="save()" ng-show="editMode">save</button>
<span ng-mouseenter="showEdit = true" ng-mouseleave="showEdit = false">
<span ng-hide="editMode" ng-click="edit()">{{model}}</span>
<a ng-show="showEdit" ng-click="edit()">edit</a>
</span>
</div>
To use it just add water:
<div ng-repeat="todo in todos"
inline-edit="todo.title"
on-save="updateTodo($index)"
on-cancel="cancelEdit(todo.title)"></div>
UPDATE:
Another option is to use the readymade Xeditable for AngularJS:
http://vitalets.github.io/angular-xeditable/
I've modified your plunker to get it working via angular-xeditable:
http://plnkr.co/edit/xUDrOS?p=preview
It is common solution for inline editing - you creale hyperlinks with editable-text directive
that toggles into <input type="text"> tag:
<a href="#" editable-text="bday.name" ng-click="myform.$show()" e-placeholder="Name">
{{bday.name || 'empty'}}
</a>
For date I used editable-date directive that toggles into html5 <input type="date">.
Since this is a common piece of functionality it's a good idea to write a directive for this. In fact, someone already did that and open sourced it. I used editablespan library in one of my projects and it worked perfectly, highly recommended.

Search form, if no value go to site

I have a search form which searchers wikipedia.com. Nothing fancy, a form with an input.
If the input is empty, currently the user is redirected here: http://en.wikipedia.org/w/index.php?title=Special%3ASearch&redirs=1&search=&fulltext=Search&ns0=1 .
Id like to redirect the users here: www.wikipedia.com instead
How can I do this?
This is my search form:
<form method="get" action="http://en.wikipedia.org/w/index.php">
<input type="hidden" value="Special:Search" name="title"/>
<input type="hidden" value="1" name="redirs"/>
<input type="text" name="search">
<input type="hidden" value="Search" name="fulltext"/>
<input type="hidden" value="1" name="ns0"/>
</form>
It's not possible, I don't think, without using JavaScript; if, as you've indicated, you're willing to use jQuery:
$('form').submit(
function(){
if ($(this).find('input:text').val() == ''){
$(this).attr('action','http://www.wikipedia.com/');
}
else {
$(this).submit();
}
});
JS Fiddle demo.
In plain JavaScript, the following seems to work (tested in Chromium 12 and Firefox 7 on Ubuntu 11.04):
var formEl = document.getElementsByTagName('form')[0];
var inputs = formEl.getElementsByTagName('input');
var textInputEl = [];
for(i in inputs){
if (inputs[i].type == 'text'){
textInputEl.push(inputs[i]);
}
}
formEl.onsubmit = function(){
if (textInputEl.value === '' || textInputEl.value === null){
this.action = 'http://www.wikipedia.com/';
}
else {
formEl.submit;
}
};
JS Fiddle demo.
I'm trying to set this up so that, with an empty text-input, the form will remove any hidden elements and then set the action, or the document.location to be http://en.wikipedia.org/wiki/Special:Random. This does not, for some reason, seem to work. Almost as if Wikipedia's finding something wrong and then redirecting to a different page. Ungh. Anyways, this is what I tried:
$('form').submit(
function(){
if ($(this).find('input:text').val() == ''){
$(this).find('input:hidden').remove();
$(this).attr('action','http://en.wikipedia.org/wiki/Special:Random');
}
else {
$(this).submit();
}
});
JS Fiddle demo;
$('form').submit(
function(){
if ($(this).find('input:text').val() == ''){
$(this).find('input:hidden').remove();
document.location.href = 'http://en.wikipedia.org/wiki/Special:Random';
/*
I also tried 'document.location','window.location'
and 'window.location.href' all of which, predictably,
failed in exactly the same way.
*/
}
else {
$(this).submit();
}
});
JS Fiddle demo;