I have prepared a simple template that displays a select box with options.
The template
<div class="jumbotron" style="background-color:white">
</div>
<div class="jumbotron container-fluid">
<h3 align="center">PAN Bulk Upload</h3>
</div>
<div class="container">
<div class="row">
<div class="col-lg-9">
<div style="border-right:1px solid #cbc6c6">
<div class="container panel-body">
<label class="custom-file-upload">
<input id="fileChoose" type="file" custom-on-change="uploadFile" />
<i class="fa fa-cloud-upload"> Choose Device Group File</i>
</label>
<hr/>
<select size=5 style="width:200px;height:100px" ng-options="o as o for o in deviceGroups">
</select>
</div>
<div class="container">
<button ng-click="validateDeviceGroups()">Validate</button>
<button ng-click="commitDeviceGroups()">Commit</button>
</div>
</div>
</div>
<div class="col-lg-3">
<textarea rows="20" cols="35"></textarea>
</div>
</div>
</div>
The Angular Controller
angapp.controller('panbulkCtrl', function($scope) {
$scope.deviceGroups = ["Hi","Hello"];
$scope.uploadFile = function() {
var filename = event.target.files[0].name;
var reader = new FileReader();
reader.onload = function (e) {
var rows = e.target.result.split("\n");
for (var i = 0; i < rows.length; i++) {
var cells = rows[i].split(",");
for (var j = 0; j < cells.length; j++) {
console.log(cells[i]);
$scope.deviceGroups.push(cells[i]);
}
}
}
reader.readAsText(event.target.files[0]);
};
$scope.validateDeviceGroups = function(){
}
});
The added strings in deviceGroups do not appear in the Select box as options. What is wrong?
As per select | AngularJS docs, ngModel is required argument.
Pass that like ng-model="selected" or something and it would work!
<select size=5 style="width:200px;height:100px" ng-model="selected"
ng-options="o as o for o in deviceGroups">
</select>
Here's working example
Please refer this. May help you try to make ng-options simpler and add ng-model for same -
var myApp = angular.module("myApp",[]);
myApp.controller("myCntr",function($scope){
$scope.deviceGroups = ["hi","hello"];
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.0/angular.min.js"></script>
<div ng-app="myApp" ng-controller="myCntr">
<select multiple size=5 style="width:200px;height:100px" ng-options="o for o in deviceGroups" ng-model="selected"/>
</div>
Try this one
ng-model="deviceGroups[0]"
Related
I am trying to learn some javascript in web programming. Starting with a simple school registration webpage: the webpage allows to dynamically create any number of grades by clicking "Grade+" button; under each grade, any number of students can be created by clicking "Student+" button. "Grade+" button works as expected, however clicking "Student+" button does not present the student information, not sure what is happening. Any help will be highly appreciated. Thanks in advance.
The reference codes:
<!DOCTYPE html>
<html>
<body>
<div>
<label>Registration</label>
<div class="form-inline justify-content-center" id="school" style="display:none">
<label for="fname">Grade:</label>
<input type="text" id="grade" name="Grade"><br><br>
<div id="students">
<div id="student">
<label for="fname">First:</label>
<input type="text" id="first" name="First"><br><br>
<label for="lname">Last:</label>
<input type="text" id="last" name="Last"><br><br>
</div>
<div class="text-center" id="add_student">
<span id="idStudentRootCopy">----S----</span>
<button type="button" onclick="addItem('student', 'idGradeRootCopy', false)">Student+</button>
</div>
</div>
</div>
<div class="text-center" id="add_grade">
<span id="idGradeRootCopy">----G----</span>
<button type="button" onclick="addItem('school', 'idGradeRootCopy', true)">Grade+</button>
</div>
</div>
<script>
var count = 0;
function addItem(id, index, root) {
var original = document.getElementById(id);
var before = document.getElementById(index);
var clone = original.cloneNode(true);
clone.style.display='block';
clone.id = id + ++count;
var newFields = clone.childNodes;
for (var i = 0; i < newFields.length; i++) {
var fieldName = newFields[i].name;
if (fieldName)
newFields[i].name = fieldName + count;
}
if (root) {
original.parentNode.insertBefore(clone, before.parentNode);
} else {
original.insertBefore(clone, before);
}
}
</script>
</body>
</html>
If you open up the developer tools of your browsers and click the Student+ button you'll get an error message like:
Uncaught DOMException: Node.insertBefore: Child to insert before is
not a child of this node
So you're actually trying to put the cloned node into the wrong spot. Either way things are a bit confusing. Let's say you have clicked the Grade+ button three times and now you decide to click on Student+ of the first clone - how should it know where to put the student as there are three grades?
Well there's a fix of course. Each Student+ button is a child of an unique clone of the school <div> which you also gave an unique id yet (school1, school2,...). So if you pass the addItem() function a reference to the button you actually clicked, we can get it's parent div like:
clickedElement.parentNode.parentNode.parentNode
and add the cloned node using appendChild() instead of insertBefore().
Here's an example (just click on 'Run code snippet'):
var count = 0;
function addItem(id, index, root, clickedElement) {
var original = document.getElementById(id);
var before = document.getElementById(index);
var clone = original.cloneNode(true);
clone.style.display = 'block';
clone.id = id + ++count;
var newFields = clone.childNodes;
for (var i = 0; i < newFields.length; i++) {
var fieldName = newFields[i].name;
if (fieldName)
newFields[i].name = fieldName + count;
}
if (root) {
original.parentNode.insertBefore(clone, before.parentNode);
} else {
clickedElement.parentNode.parentNode.parentNode.appendChild(clone);
}
}
<div>
<label>Registration</label>
<div class="form-inline justify-content-center" id="school" style="display:none">
<label for="fname">Grade:</label>
<input type="text" id="grade" name="Grade"><br><br>
<div id="students">
<div id="student">
<label for="fname">First:</label>
<input type="text" id="first" name="First"><br><br>
<label for="lname">Last:</label>
<input type="text" id="last" name="Last"><br><br>
</div>
<div class="text-center" id="add_student">
<span id="idStudentRootCopy">----S----</span>
<button type="button" onclick="addItem('student', 'idGradeRootCopy', false,this)">Student+</button>
</div>
</div>
</div>
<div class="text-center" id="add_grade">
<span id="idGradeRootCopy">----G----</span>
<button type="button" onclick="addItem('school', 'idGradeRootCopy', true,this)">Grade+</button>
</div>
</div>
Update
If you click on the Grade+ button, it will automatically also 'create' a student input field as it's div is part of the school div. So move it out of the school div and change it's display mode to none.
If you want the new student input field to appear right before the Student+ button, we indeed need to use .insertBefore().
Here's the modified example:
var count = 0;
function addItem(id, index, root, clickedElement) {
var original = document.getElementById(id);
var before = document.getElementById(index);
var clone = original.cloneNode(true);
clone.style.display = 'block';
clone.id = id + ++count;
var newFields = clone.childNodes;
for (var i = 0; i < newFields.length; i++) {
var fieldName = newFields[i].name;
if (fieldName)
newFields[i].name = fieldName + count;
}
if (root) {
original.parentNode.insertBefore(clone, before.parentNode);
} else {
clickedElement.parentNode.insertBefore(clone, clickedElement);
}
}
<div>
<label>Registration</label>
<div id="student" style="display:none">
<label for="fname">First:</label>
<input type="text" id="first" name="First"><br><br>
<label for="lname">Last:</label>
<input type="text" id="last" name="Last"><br><br>
</div>
<div class="form-inline justify-content-center" id="school" style="display:none">
<label for="fname">Grade:</label>
<input type="text" id="grade" name="Grade"><br><br>
<div id="students">
<div class="text-center" id="add_student">
<span id="idStudentRootCopy">----S----</span>
<button type="button" onclick="addItem('student', 'idStudentRootCopy', false,this)">Student+</button>
</div>
</div>
</div>
<div class="text-center" id="add_grade">
<span id="idGradeRootCopy">----G----</span>
<button type="button" onclick="addItem('school', 'idGradeRootCopy', true,this)">Grade+</button>
</div>
</div>
in jsfiddle im trying to make a configuration generator for an app i have, basically the format is as follows:
type;user;pass;ip:port
with ip:port being optional
it would be generated from a selectbox two textboxes, where its inputted as user:pass and in the other ip:port, if you don't understand, this is a little visual ive made:
pic of what i want
For what it's worth:
document.querySelector('button').addEventListener('click', function() {
var type = document.getElementById('type').value;
var useipport = document.getElementById('useipport').checked;
var userpass = document.getElementById('userpass').value;
var ipport = document.getElementById('ipport').value;
var output = document.getElementById('output');
var users = [],
ips = [],
config = [];
if (userpass.length > 0) users = userpass.split('\n');
if (ipport.length > 0) ips = ipport.split('\n');
var ix = 0;
while (ix < users.length || ix < ips.length) {
var user = '';
user += type + ';';
if (users[ix]) user += users[ix] + ';';
if (useipport && ips[ix]) user += ips[ix];
config.push(user);
ix++;
}
output.value = config.join("\n");
});
<link href="//cdnjs.cloudflare.com/ajax/libs/skeleton/2.0.4/skeleton.min.css" rel="stylesheet"/>
<div class="container">
<div class="row">
<div class="six columns">
<select id="type">
<option value="PT">PT</option>
<option value="GL">GL</option>
</select>Type
</div>
<div class="six columns">
<label>
<input type="checkbox" id="useipport">
<span class="label-body">Use IP/Port</span>
</label>
</div>
</div>
<div class="row">
<div class="six columns">
<textarea class="u-full-width" placeholder="abc:123" id="userpass"></textarea>
</div>
<div class="six columns">
<textarea class="u-full-width" placeholder="1.1.1.1:1111" id="ipport"></textarea>
</div>
</div>
<div class="row">
<div class="six columns">
<textarea class="u-full-width" id="output"></textarea>
</div>
<div class="six columns">
<button>Create</button>
</div>
</div>
</div>
I have a list of select boxes. On change of each select box, i need to save the selected option in a variable (can be array not sure). As of now I am able to save the selected value in a variable if there is only ONE select box. How do i do it if I have a group of select boxes which has been populated using ng-repeat? I am able to display the changed value (in the h4 tag on the page). But I want to save that value into a variable. How do I do that?
Link to Fiddle
var app=angular.module("myApp",[]);
app.controller("myCtrl",function($scope){
$scope.GetValue = function(value){
alert($scope.lengthPwd);
}
$scope.parameterList = [
{id:"one", text:'Is it red in color?', done:true},
{id:"two", text:'Is it square shaped?', done:false},
{id:"three", text:'Does it have vowels?', done:false},
{id: "four", text:'Allow Repeated characters?', done:true}
];
$scope.range = function(min, max, step){
step = step || 1;
var input = [];
for (var i = min; i <= max; i += step) input.push(i);
return input;
}
})
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.19/angular.min.js"></script>
<body ng-app="myApp">
<div ng-controller="myCtrl">
<label>Enter the total length
<select class="form-control col-md-6" ng-change="GetValue()" ng-model="lengthPwd">
<option ng-repeat="n in range(1,100)">{{n}}</option>
</select>
</label>
<ul class="row unstyled cards col-md-offset-1">
<li class="col-lg-4 col-md-5 card" ng-repeat="parameter in parameterList">
<label id="sliderLabel">
<input type="checkbox" ng-model="parameter.done">
<span>{{parameter.text}}</span>
</label>
<select class="form-control" ng-hide="!parameter.done" ng-disabled="anyNum=='any'" ng-change="GetAllVal()" ng-model="test" disabled>
<option ng-repeat="n in range(1,100)">{{n}}</option>
</select>
<h4 id="{{parameter.id+test}}">{{parameter.id+test}}</h4>
</li>
</ul>
</div>
</body>
If I understand your problem correctly, you want to store the values of the four select properties. I have copied your code and added the required logic.
The values chosen from the selectors will be stored in an array. You can access the values based on their position in the array. This is a limited solution but it should give you a hand in the right direction.
Reference
var app=angular.module("myApp",[]);
app.controller("myCtrl",function($scope){
$scope.GetValue = function(value){
alert($scope.lengthPwd);
}
$scope.parameterList = [
{id:"one", text:'Is it red in color?', done:true},
{id:"two", text:'Is it square shaped?', done:false},
{id:"three", text:'Does it have vowels?', done:false},
{id: "four", text:'Allow Repeated characters?', done:true}
];
$scope.valuesArr = [];
$scope.range = function(min, max, step){
step = step || 1;
var input = [];
for (var i = min; i <= max; i += step) input.push(i);
return input;
}
})
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.19/angular.min.js"></script>
<body ng-app="myApp">
<div ng-controller="myCtrl">
<label>Enter the total length
<select class="form-control col-md-6" ng-change="GetValue()" ng-model="lengthPwd">
<option ng-repeat="n in range(1,100)">{{n}}</option>
</select>
</label>
<ul class="row unstyled cards col-md-offset-1">
<li class="col-lg-4 col-md-5 card" ng-repeat="parameter in parameterList track by $index">
<label id="sliderLabel">
<input type="checkbox" ng-model="parameter.done">
<span>{{parameter.text}}</span>
</label>
<select class="form-control" ng-hide="!parameter.done" ng-disabled="anyNum=='any'" ng-change="GetAllVal()" ng-model="valuesArr[$index]" disabled>
<option ng-repeat="n in range(1,100)" ng-value="n">{{n}}</option>
</select>
<h4 id="{{parameter.id+test}}">{{parameter.id+test}}</h4>
</li>
</ul>
<h4> Stored Values -> {{valuesArr}}</h4>
</div>
</body>
If I understood well your problem you want to get the values selected in the respective <select> right?
Point 1: I extremely recommend you to use ngOptions instead of ngRepeat. ngOptions was made exactly for <select> tag.
Point 2: ngRepeat creates its own scope so no longer you can access directly the ngModel inside it, then you should use preferably controller-as-syntax.
You can do it using ngModel as array, like this:
angular.module("app", [])
.controller("mainCtrl", function() {
var vm = this;
vm.GetValue = function(value) {
alert(vm.lengthPwd);
}
vm.parameterList = [
{
"id":"one",
"text":"Is it red in color?",
"done":true
},
{
"id":"two",
"text":"Is it square shaped?",
"done":false
},
{
"id":"three",
"text":"Does it have vowels?",
"done":false
},
{
"id":"four",
"text":"Allow Repeated characters?",
"done":true
}
];
vm.input = [];
for (var i = 1; i <= 100; i++) {
vm.input.push(i);
}
vm.set_value = function(index) {
vm.parameterList[index].selectValue = vm.test[index];
}
})
<!DOCTYPE html>
<html ng-app="app">
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.7/angular.min.js"></script>
</head>
<body ng-controller="mainCtrl as main">
<pre ng-bind="main.test | json"></pre>
<ul class="row unstyled cards col-md-offset-1">
<li class="col-lg-4 col-md-5 card" ng-repeat="parameter in main.parameterList track by $index">
<label id="sliderLabel">
<input type="checkbox" ng-model="parameter.done">
<span ng-bind="parameter.text"></span>
</label>
<select class="form-control" ng-if="parameter.done" ng-options="n for n in main.input" ng-model="main.test[$index]" ng-change="main.set_value($index)" ng-disabled="anyNum == 'any'">
<option value="">Select</option>
</select>
<h4 id="{{parameter.id+test}}" ng-bind="parameter.id + main.test[$index]"></h4>
</li>
</ul>
</body>
</html>
try this:
$scope.boxValue = [];
$scope.boxValueChange = function (key,val) {
$scope.boxValue[key] = val;
console.log($scope.boxValue);
}
https://jsfiddle.net/r3bw4qka/5/
I'm trying to write some JavaScript that could be used throughout my app, and allow a checkbox to show/hide a nearby element.
If I have these elements:
<div class="optionable" style="display: block;">
<div class="row">
<div class="col-md-2">
<input checked="checked" class="form-control"
data-val="true" id="IsActive"
name="IsActive"
onclick="CheckboxOptionsToggle(this);"
type="checkbox" value="true">
</div>
<div class="col-md-8">
Chapter
</div>
</div>
<div class="row options">
<div class="col-md-12">
Some data here...
</div>
</div>
</div>
And this script:
CheckboxOptionsToggle = function (thisCheckbox) {
debugger;
var optionElement = $('.options');
if (thisCheckbox.checked) {
$(thisCheckbox).closest(optionElement).show();
} else {
$(thisCheckbox).closest(optionElement).hide();
}
}
But this isn't working. I would like the checkbox with the onclick="CheckboxOptionsToggle(this);" to trigger the options element in the same optionable div to either show or hide.
What am I doing wrong in my JavaScript/jQuery?
UPDATE: This is my final solution:
$('.optionToggle').on('change', function () {
$(this).closest('.optionable').find('.options').toggle(this.checked);
});
$(document).ready(function () {
var toggleElements = document.body.getElementsByClassName('optionToggle');
for (var i = 0; i < toggleElements.length; i++) {
var thisCheck = $(toggleElements[i]);
thisCheck.closest('.optionable').find('.options').toggle(thisCheck.prop('checked'));
}
});
<div class="optionable" style="display: block;">
<div class="row">
<div class="col-md-2">
<input checked="checked" class="form-control optionToggle"
data-val="true" id="IsActive"
name="IsActive"
type="checkbox" value="true">
</div>
<div class="col-md-8">
Chapter
</div>
</div>
<div class="row options">
<div class="col-md-12">
Some data here...
</div>
</div>
</div>
Be more generic, and stop using inline event handlers
$('[type="checkbox"]').on('change', function() { // or use class to not attach to all
$(this).closest('.optionable').find('.options').toggle(this.checked);
}).trigger('change');
FIDDLE
You can change it like
CheckboxOptionsToggle = function (thisCheckbox) {
debugger;
var optionElement = $('.options');
if (thisCheckbox.checked) {
$(thisCheckbox)..closest('div.optionable').find(optionElement).show();
} else {
$(thisCheckbox)..closest('div.optionable').find(optionElement).hide();
}
}
I would stay away from .closes, because it is so specific, instead I would go with more reusable code like so:
HTML:
<input type="checkbox" id="toggler" data-target-class="some-div" class="toggler" value="myValue" checked> Toggle Me
<div class="some-div">
Some Text within the div.
</div>
JS:
$('#toggler').on('click', function() {
var targetClass = $(this).data('target-class');
$('.' + targetClass).toggle($(this).checked);
});
JSFiddler: https://jsfiddle.net/ro17nvbL/
I am using data element on the checkbox to specifiy which divs to show or hide. This allows me to not only hide/show divs but anything n the page, and not only one instance but as many as needed. Way more flexible - still does the same job.
My website has 3 services, I want to be able to click on service 1 and see menu 1, click on service 2 and see menu 2, click on service 3 and see menu 3. I have the following code but it is not working as expected. When I click on service 2 and service 3, nothing shows up.
HTML :
<div class="row" id="menu_service1">
<div class="col-md-4">
<span><h5>Choose a line</h5> <select id="lines" class="form-control"></select></span>
<span><h5>Choose a stop</h5> <select id="stop" class="form-control"></select></span>
</div>
</div>
<div class="row" id="menu_service2">
<div class="col-md-4">
<span><h5>Choose a stop</h5> <select id="stop" class="form-control"></select></span>
<span><h5>Choose a stop</h5> <select id="stop" class="form-control"></select></span>
</div>
</div>
<div class="row" id="menu_service3">
<div class="col-md-4">
<p>blah</p>
</div>
</div>
JS :
$(document).ready(function() {
var line_array = ["Line 1", "Line 2", "Line 3"];
var stops = ["stop1", "stop2", "stop3"] ;
for (var i = 0; i < line_array.length; i++) {
$('#lines').append('<option>' + line_array[i] + '</option>');
}
for (var i = 0; i < stops.length; i++) {
$('#stop').append('<option>' + stops[i] + '</option>');
}
$('#menu_service1').hide();
$('#menu_service2').hide();
$('#menu_service3').hide();
$('#Service_1').click(function() {
$('#menu_service1').toggle();
});
$('#Service_2').click(function() {
$('#menu_service2').toggle();
});
$('#Service_3').click(function() {
$('#menu_service3').toggle();
});
});
Working Fiddle.
id should be unique in same document, so try to replace the duplicated ones by general classes, e.g:
<span><h5>Choose a line</h5> <select class="form-control lines"></select></span>
<span><h5>Choose a stop</h5> <select class="form-control stop"></select></span>
And in your JS use them with class selector dot ., like :
$('.lines').append('<option>' + line_array[i] + '</option>');
You should also fix the typos in the following two lines by adding id selector sogn # :
$('menu_service2').toggle();
$('menu_service2').toggle();
Should be :
$('#menu_service2').toggle();
$('#menu_service2').toggle();
Also you could use comma , separator for multiple selectors, so instead of :
$('#menu_service1').hide();
$('#menu_service2').hide();
$('#menu_service3').hide();
Use just :
$('#menu_service1,#menu_service2,#menu_service3').hide();
Hope this helps.
$(document).ready(function() {
var line_array = ["Line 1", "Line 2", "Line 3"];
var stops = ["stop1", "stop2", "stop3"] ;
for (var i = 0; i < line_array.length; i++) {
$('.lines').append('<option>' + line_array[i] + '</option>');
}
for (var i = 0; i < stops.length; i++) {
$('.stop').append('<option>' + stops[i] + '</option>');
}
$('#menu_service1,#menu_service2,#menu_service3').hide();
$('#Service_1').click(function() {
$('.row').hide();
$('#menu_service1').toggle();
});
$('#Service_2').click(function() {
$('.row').hide();
$('#menu_service2').toggle();
});
$('#Service_3').click(function() {
$('.row').hide();
$('#menu_service3').toggle();
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link href="https://netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://netdna.bootstrapcdn.com/bootstrap/3.0.0/js/bootstrap.min.js"></script>
<button id='Service_1'>Service 1</button>
<button id='Service_2'>Service 2</button>
<button id='Service_3'>Service 3</button>
<div class="row" id="menu_service1">
<div class="col-md-4">
<span><h5>Choose a line1</h5> <select class="form-control lines"></select></span>
<span><h5>Choose a stop1</h5> <select class="form-control stop"></select></span>
</div>
</div>
<div class="row" id="menu_service2">
<div class="col-md-4">
<span><h5>Choose a line2</h5> <select class="form-control lines"></select></span>
<span><h5>Choose a stop2</h5> <select class="form-control stop"></select></span>
</div>
</div>
<div class="row" id="menu_service3">
<div class="col-md-4">
<p>blah</p>
</div>
</div>
You forgot the # sign in front of the id's in your selectors.
$('#menu_service2').toggle();
$('#menu_service3').toggle();
I prefer to write less lines of code to obtain the same result.
$(function () {
var line_array = ["Line 1", "Line 2", "Line 3"];
var stops = ["stop1", "stop2", "stop3"] ;
for (var i = 0; i < line_array.length; i++) {
$('[id^=lines]').append('<option>' + line_array[i] + '</option>');
}
for (var i = 0; i < stops.length; i++) {
$('[id^=stop]').append('<option>' + stops[i] + '</option>');
}
$('[id^=menu_service]').hide();
$('[id^=Service_]').click(function() {
var currDiv = this.getAttribute('data-div');
$('div.row:not(#' + currDiv + ')').hide();
$('#' + currDiv).toggle();
});
});
<script src="http://code.jquery.com/jquery-1.11.3.min.js"></script>
<button id='Service_1' data-div="menu_service1">Service 1</button>
<button id='Service_2' data-div="menu_service2">Service 2</button>
<button id='Service_3' data-div="menu_service3">Service 3</button>
<div class="row" id="menu_service1">
<div class="col-md-4">
<span><h5>Choose a line</h5> <select id="lines1" class="form-control"></select></span>
<span><h5>Choose a stop</h5> <select id="stop1" class="form-control"></select></span>
</div>
</div>
<div class="row" id="menu_service2">
<div class="col-md-4">
<span><h5>Choose a stop</h5> <select id="stop2" class="form-control"></select></span>
<span><h5>Choose a stop</h5> <select id="stop2" class="form-control"></select></span>
</div>
</div>
<div class="row" id="menu_service3">
<div class="col-md-4">
<p>blah</p>
</div>
</div>