JavaScript: Push each querySelectorAll result into variable - javascript

can you see what i'm trying to do here? I want to push some objects into a variable but keep it all tidy and contained.
var toggles = document.querySelectorAll('[data-search-toggle]').forEach(function(el) {
this.push({ 'element': el, 'select': el.dataset });
});
Obviously the code above doesn't work, that's just the concept of what I want, so if I was to console.log toggles below this I would get along the lines of:
[
{
'element': [Object],
'select': 'dropdown-search__select--make'
},
{
'element': [Object],
'select': 'dropdown-search__select--make'
},
{
'element': [Object],
'select': 'dropdown-search__select--make'
},
]
Edit:
Or would I need to do something like this:
var tmp;
var toggles = document.querySelectorAll('[data-search-toggle]').forEach(
tmp.push(function(el) {
return { 'element': el, 'select': el.dataset };
})
);
HTML:
<input type="radio" class="dropdown-search__radio" name="vehtype" id="dropdown-search__vehtype--cars" value="cars" checked required data-search-toggle="dropdown-search__select--make">
<label class="dropdown-search__label--radio" for="dropdown-search__vehtype--cars">Cars</label>
<input type="radio" class="dropdown-search__radio dropdown-search__radio" name="vehtype" id="dropdown-search__vehtype--vans" value="vans" data-search-toggle="dropdown-search__select--make">
<label class="dropdown-search__label--radio" for="dropdown-search__vehtype--vans">Vans</label>
<input type="radio" class="dropdown-search__radio dropdown-search__radio" name="vehtype" id="dropdown-search__vehtype--bikes" value="bikes" data-search-toggle="dropdown-search__select--make">
<label class="dropdown-search__label--radio" for="dropdown-search__vehtype--bikes">Bikes</label>

You can convert the result of querySelectorAll to an array with the Array.from function and pass a map function as the second argument to wrap each of the elements in an object.
const toggles = Array.from(document.querySelectorAll('[data-search-toggle]'), (el) => {
return {
element: el,
select: el.dataset
};
});
console.log(toggles);
<input type="radio" class="dropdown-search__radio" name="vehtype" id="dropdown-search__vehtype--cars" value="cars" checked required data-search-toggle="dropdown-search__select--make">
<label class="dropdown-search__label--radio" for="dropdown-search__vehtype--cars">Cars</label>
<input type="radio" class="dropdown-search__radio dropdown-search__radio" name="vehtype" id="dropdown-search__vehtype--vans" value="vans" data-search-toggle="dropdown-search__select--make">
<label class="dropdown-search__label--radio" for="dropdown-search__vehtype--vans">Vans</label>
<input type="radio" class="dropdown-search__radio dropdown-search__radio" name="vehtype" id="dropdown-search__vehtype--bikes" value="bikes" data-search-toggle="dropdown-search__select--make">
<label class="dropdown-search__label--radio" for="dropdown-search__vehtype--bikes">Bikes</label>

You can use spread element to convert NodeList to an Array, .map() to return an object for each element of array. To get the .dataset where property contains - characters between word characters, camel case the property reference
var toggles = [...document.querySelectorAll("[data-search-toggle]")].map(el =>
({ "element": el, "select": el.dataset.searchToggle })
});

Related

How to find out the value of an input which already changed

I have3 inputs which each of which has a specific value.
<input type="text" id="inputType" v-model="add_sale.type">
<input type="text" id="inputId" v-model="add_sale.id">
<input type="text" dir="auto" v-model="add_sale.name" id="inputName" class="form-control" placeholder="Material" readonly style="background: #fff;">
I change any of the input values like this:
new Vue({
data() {
return{
material:{
name: "niaz",
id: 1,
type: "human"
},
add_sale: {}
}
},
mounted() {
document.getElementById("inputName").value = this.material.name;
document.getElementById("inputId").value = this.material.id;
document.getElementById("inputType").value = this.material.type;
}
})
Now I need to watch the values that changed before.
I want to know if there is any way to find out what is the value of one of the inputs which changed before and change the name input to Alex if the type was human.
Dude,
If I understand you correctly.
you are looking for something to track your previous value.
with Vuejs you can do it very easily. and one more important thing. when you are using vue you don't need to be dependent on vanilla Javascript
so what you are looking for is something is gonna be like this,
new Vue({
data() {
return{
type : null,
id: null,
name: null,
add_sale: {}
}
},
watch: {
type(oldvalue, newvalue) {
//do whatever you want to do
},
id(oldvalue, newvalue) {
//do whatever you want to do
},
name(oldvalue, newvalue) {
//do whatever you want to do
},
},
mounted() {
this.type = 'something' //initial the value
this.id = 1243 //intial value
this.name = 'name' //initial value
}
})
<input type="text" id="inputType" v-model="type">
<input type="text" id="inputId" v-model="id">
<input type="text" dir="auto" v-model="name" id="inputName" class="form-control" placeholder="Material" readonly style="background: #fff;">
so you can do it easily with vuejs watch which pretty much work like on change event listener.
and the parameter oldvalue where you will have the previous data, newvalue is the current data you change

Jquery DataTable checkboxes

I am using jquery datatable with two checkbox columns with a checkall checkbox for each column in the table header. I am looping through all the checkboxes in the datatable for every change event on a checkbox to make sure the checkAll checkbox is checked/unchecked which results in a lag when user checks a checkbox.
Below is the code snippet. Please let me know if there any other way I can do this to improve the performance.
ntfcTable.$('.ntfcInd')
.change(
function() {
let counterNtfcCh = 0;
for (let i = 0; i < ntfcTableNodes.length; i++) {
if (ntfcTable.$('input[type="checkbox"][id="ntfcInd[' + i + ']"]').is(":checked") === true) {
counterNtfcCh++;
}
}
counterNtfcCh === ntfcTableNodes.length ? ntfcCheckAll.prop("checked", true)
: ntfcCheckAll.prop("checked", false);
checkBoxState = true;
});
Hopefully this will help. I am assuming that ntfcTable is a jQuery object. You don't need to search ntfcTable every time you loop through the table. The first line will grab all checkboxes in the table. jQuery objects have a length property so they can actually be looped over. This should work as long as you are not adding and removing checkboxes on the fly.
var ntfcTableNodes = ntfcTable.$('input[type="checkbox"]');
ntfcTableNodes.change(
function() {
let counterNtfcCh = 0;
for (let i = 0; i < ntfcTableNodes.length; i++) {
let checkNode = ntfcTableNodes[i];
if ( checkNode.is(":checked") === true ) {counterNtfcCh++;}
}
counterNtfcCh === ntfcTableNodes.length ? ntfcCheckAll.prop("checked", true)
: ntfcCheckAll.prop("checked", false);
checkBoxState = true;
});
Instead of looping through the checkboxes, you can just check the length of the checked checkboxes like this:
alert($('input[type="checkbox"]:checked').length);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input type="checkbox" name="vehicle" value="Bike"> I have a bike<br>
<input type="checkbox" name="vehicle" value="Car" checked> I have a car<br><input type="checkbox" name="vehicle" value="Bike"> I have a bike<br>
<input type="checkbox" name="vehicle" value="Car" checked> I have a car<br><input type="checkbox" name="vehicle" value="Bike"> I have a bike<br>
<input type="checkbox" name="vehicle" value="Car" checked> I have a car<br><input type="checkbox" name="vehicle" value="Bike"> I have a bike<br>
<input type="checkbox" name="vehicle" value="Car" checked> I have a car<br><input type="checkbox" name="vehicle" value="Bike"> I have a bike<br>
<input type="checkbox" name="vehicle" value="Car" checked> I have a car<br>
Or for you case, it's like this:
if(ntfcTable.$('input[type="checkbox"]:checked').length == ntfcTableNodes.length)
Even though, the question is marked 'Answered' to those, who may face that same problem, solution, for which OP has requested, basically, boils down to one nice and neat one-liner:
const ifAllChecked = col => dataTable.rows().nodes().toArray().every(row => $(row).find(`td:eq(${col}) [type="checkbox"]`).is(':checked'));
Following is the brief DEMO of how it can be done:
//define source data
const srcData = [
{city: 'Kyiv', visited: true, enjoyed: true},
{city: 'Istanbul', visited: true, enjoyed: true},
{city: 'Moscow', visited: true, enjoyed: false},
{city: 'Nicosia', visited: true, enjoyed: true},
{city: 'New York', visited: false, enjoyed: false},
{city: 'Cairo', visited: true, enjoyed: true}
];
//define datatables object
const dataTable = $('#mytable').DataTable({
sDom: 'tp',
pageLength: 3,
data: srcData,
columns: [
{title: 'city', data: 'city'},
{
title: 'visited',
data: 'visited',
render: (data, type, row, meta) => `<input type="checkbox" colindex="${meta.col}" ${data ? 'checked' : ''} style="float:right;margin-right:28px" class="regularchckbx"></input>`
},
{
title: 'enjoyed',
data: 'enjoyed',
render: (data, type, row, meta) => `<input type="checkbox" colindex="${meta.col}" ${data ? 'checked' : ''} style="float:right;margin-right:28px" class="regularchckbx"></input>`
},
]
});
//essential part of the solution OP was looking for
const ifAllChecked = col => dataTable.rows().nodes().toArray().every(row => $(row).find(`td:eq(${col}) [type="checkbox"]`).is(':checked'));
//put 'check all' checkboxes into header
$(dataTable.columns([1,2]).header()).append(`<input type="checkbox" class="allchecked" style="float:right;margin-right:20px"></input>`);
//set initial header checkboxes state
[1, 2].forEach( col => dataTable.column(col).header().querySelector('[type="checkbox"]').checked = ifAllChecked(col));
//listen for changes and adjust 'check-alls'
$('#mytable').on('click', '.regularchckbx', function(){
dataTable.column($(this).attr('colindex')).header().querySelector('[type="checkbox"]').checked = ifAllChecked($(this).attr('colindex'));
});
//check/uncheck all
$('.allchecked').on('click', function(){
let col = dataTable.column($(this).closest('th')).index();
let state = this.checked;
dataTable.rows().every(function(){
this.node().querySelector(`[colindex="${col}"]`).checked = state;
});
});
<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.10.19/css/jquery.dataTables.min.css">
<script type="application/javascript" src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script type="application/javascript" src="https://cdn.datatables.net/1.10.19/js/jquery.dataTables.min.js"></script>
</head>
<body>
<table id="mytable"></table>
</body>
</html>

Get name and id of autocomplete suggestions into input field

I have the code below, which I use to type and suggest a few relation names in an input field. The data variable right now returns only names like:
var data = ["name": "Relation 1", "name":"Relation 2"]
I modified it and now it has data like:
var data = [
{"id":1,"name":"Foo"},
{"id":2,"name":"Bar"},
{"id":3,"name":"Foo Bar"}
];
How do I append the id of the selected name in the id input?
$('input.relation').typeahead({
source: function (query, process) {
return $.get('live_search.php?filter=relation', { query: query }, function (data) {
console.log(data);
data = $.parseJSON(data);
return process(data);
});
}
});
<div class="form-group">
<label for="relation"> Relation </label>
<input class="relation form-control" type="text">
<input class="relation-id form-control" type="text" name="id">
</div>

Create JSON in specific format

I need send a json via post to api in this format:
"answer" => {
"name"=>"Test",
"email"=>"test#test.com",
"hospital"=>"Hospital Name",
"answered_questions_attributes"=>{
"0"=>{
"value"=>"1",
"question_id"=>"1"
},
"1"=>{
"value"=>"0",
"question_id"=>"2"
},
"2"=>{
"value"=>"1",
"question_id"=>"3"
}
}
}
I get the "answered_questions_attributes" data from inputs, the values are true or false and the name of the input is the question ID, eg:
<div class="resp_val_div">
<input type="hidden" name="1" value="1" />
<input type="hidden" name="2" value="0" />
<input type="hidden" name="3" value="1" />
</div>
I tried the code below, but this only returns a incorrect json:
var resp_val = jQuery(".resp_val_div").find("input");
var dados = {
"name": jQuery("#name").val(),
"email": jQuery("#email").val(),
"hospital": jQuery(".answer_hospital").val(),
'answered_questions_attributes':[]
};
resp_val.each(function(index, el) {
d = {"value":parseInt(el.value), "question_id":el.name};
dados.answered_questions_attributes.push(d);
});
console.log(dados);
"answer"=>{
"name"=>"Test",
"email"=>"test#test.com",
"hospital"=>"Hospital Test",
"answered_questions_attributes"=>[
{
"value"=>1,
"question_id"=>"1"
},
{
"value"=>0,
"question_id"=>"2"
},
{
"value"=>1,
"question_id"=>"3"
}
]
}
How can i create the first json in this case?
Don't use an array and .push() if you want an object. And don't use parseInt() if you want the value property to be a string rather than a number.
var dados = {
"name": jQuery("#name").val(),
"email": jQuery("#email").val(),
"hospital": jQuery(".answer_hospital").val(),
'answered_questions_attributes':{}
};
resp_val.each(function(index, el) {
d = {"value":el.value, "question_id":el.name};
dados.answered_questions_attributes[index] = d;
});

jQuery: pushing array of values in serializeArray

I have these:
<input class="orders" name="orders[]" value="1">
<input class="orders" name="orders[]" value="2">
<input class="orders" name="orders[]" value="3">
I try add values of orders to an serializeArray in JQUERY.
I do this:
var datastring = $("#form1").serializeArray();
var orders = [];
$('input.orders').each(function() {
orders.push($(this).val());
});
datastring.push({name: "orders", value: orders});
in server side,(when I convert it into a json format) I want ["1","2","3"]
but now only I get a string:1,2,3
I try change it to:
datastring.push({name: "orders[]", value: orders});
Now when I convert it to json string (in server side) I get this:
["1,2,3"]
can please tell me my mistake?
What you want is an array with objects that have the same name
var datastring = $("#form1").serializeArray();
$('input.orders').each(function() {
datastring.push({name: this.name, value: this.value});
});
And make you sure you use the correct class, remove the brackets
<input class="orders" name="orders[]" value="1">
<input class="orders" name="orders[]" value="2">
<input class="orders" name="orders[]" value="3">
This will give you an array looking like
[
{
"name": "orders[]",
"value": "1"
},
{
"name": "orders[]",
"value": "2"
},
{
"name": "orders[]",
"value": "3"
}
]
jQuery will in turn parse that array to the string orders[]=1&orders[]=2&orders[]=3 when submitted, which is what most serverside languages that parse [] as form groups expect, both the key and the value for each element.
Just try joining the array:
Example snippet for reference:
var datastring = [];
datastring.push({
name: "orders",
value: ['1', '2', '3'].join(',')
});
console.log(datastring[0]["value"])

Categories