I am trying to save the values of multiple multi selects as one object ...
Here is what I am trying to do. I have 3 select boxes and am using the ChosenJS library for better ui.
All 3 multi-selects are using the same model (should this change?)
HTML
<div id="app">
<select multiple v-chosen v-model="choices" name="filters1" id="filters1">
<option value="1">Option 1</option>
<option value="2">Option 2</option>
<option value="3">Option 3</option>
</select>
<select multiple v-chosen v-model="choices" name="filters2" id="filters2">
<option value="4">Option 4</option>
<option value="5">Option 5</option>
<option value="6">Option 6</option>
</select>
<select multiple v-chosen v-model="choices" name="filters3" id="filters3">
<option value="7">Option 7</option>
<option value="8">Option 8</option>
<option value="9">Option 9</option>
</select>
<pre>
Selected Options: {{choices}}
</pre>
</div>
JS
Vue.directive('chosen', {
twoWay: true,
bind: function () {
return this.vm.$nextTick((function (_this) {
return function () {
return $(_this.el).chosen({
inherit_select_classes: false,
width: '100%'
}).change(function (ev) {
var i, len, option, ref, values;
if (_this.el.hasAttribute('multiple')) {
values = [];
ref = _this.el.selectedOptions;
for (i = 0, len = ref.length; i < len; i++) {
option = ref[i];
values.push(option.value);
}
console.log(values);
return _this.set(values);
} else {
return _this.set(_this.el.value);
}
});
};
})(this));
},
update: function (nv, ov) {
return $(this.el).trigger('chosen:updated');
}
});
var app = new Vue({
el:'#app',
data: {
choices: []
}
})
My expected outcome would be:
Selected Options: ['2','3','6','8']
Is this possible?
I created a fiddle to show where I am at.
http://jsfiddle.net/tyLa562h/3/
No, you can't. Only radio buttons and checkboxes can have same model. So, here what you can do it by using a computed option: (choice1, choice2, choice3 are all three different model)
computed: {
allChoices: function() {
return this.choice1 + this.choice2 + this.choice3; // return how you want
}
}
You can even use getter/setter method if you want.
Related
The Issue
I am trying to convert form inputs to a json object but having difficulty trying to achieve this, below is a snippet of the HTML which I have and the JSON which I'm trying to get.
{
"2019-01-23": [
{
id: 1,
period: 'am'
},
{
id: 2,
period: 'pm'
}
]
}
<select name="dates[2019-01-23][0][id]">
<option value="1" selected>1</option>
<option value="2">2</option>
<option value="3">3</option>
</select>
<select name="dates[2019-01-23][0][period]">
<option selected>am</option>
<option>pm</option>
</select>
<select name="dates[2019-01-23][1][id]">
<option value="1">1</option>
<option value="2" selected>2</option>
<option value="3">3</option>
</select>
<select name="dates[2019-01-23][1][period]">
<option>am</option>
<option selected>pm</option>
</select>
What I've tried
var inputs = $(':input').serializeArray();
var json = [];
$.each(inputs, function(key, input) {
var names = input.name.split(/\[(.*?)\]/);
var data = [];
data[names[1]] = [];
data[names[1]][names[3]] = { id: null, period: null };
if(names[5] == 'id') {
data[names[1]][names[3]].id = input.value;
}
if(names[5] == 'period') {
data[names[1]][names[3]].period = input.value;
}
json.push(data);
});
But this doesn't quite achieve what I'm after (multiple of the same date) and I'm getting a bit lost now, I'm sure there must be a way of doing this a lot easier.
First, match is more appropriate for your case than split.
Furthermore, since json is object literal, it should be initialised with empty object ({}), not array.
push is not quite appropriate for your case. It's better to use direct assignment instead.
So the code might look like this:
var inputs = $(':input').serializeArray();
var json = {};
$.each(inputs, function(key, input) {
var keys = input.name.match(/([^\[\]]+)/g).slice(1);
var date = keys[0], i = keys[1], id = keys[2];
if (!json[date]) json[date] = [];
if (!json[date][i]) json[date][i] = {};
json[date][i][id] = input.value;
});
console.log(JSON.stringify(json));
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.0.0/jquery.min.js"></script>
<select name="dates[2019-01-23][0][id]">
<option value="1" selected>1</option>
<option value="2">2</option>
<option value="3">3</option>
</select>
<select name="dates[2019-01-23][0][period]">
<option selected>am</option>
<option>pm</option>
</select>
<select name="dates[2019-01-23][1][id]">
<option value="1">1</option>
<option value="2" selected>2</option>
<option value="3">3</option>
</select>
<select name="dates[2019-01-23][1][period]">
<option>am</option>
<option selected>pm</option>
</select>
I dynamically generate additional forms on a page using Django Model Formsets. The user can generate as many forms as they need. This is done in a Vuejs method.
My issue is changing the options of the second select of the form that the first select value was chosen. I was thinking about trying on focus or on click to get the select that was last changed, but I'm not sure how that would work.
I do track the current count of forms on the page.
In the example below. If the user changed form_select_0 to One, I need form_subselect_0 to only have options C and D, but the selects in form_1 should not be altered.
Example:
<form id = form_0>
<select id="form_select_0">
<option value="one">One</option>
<option value="two">Two</option>
</select>
<select id="form_subselect_0">
<option value="A">A</option>
<option value="B">B</option>
<option value="C">C</option>
<option value="D">D</option>
</select>
</form>
<form id = form_0>
<select id="form_select_1">
<option value="one">One</option>
<option value="two">Two</option>
</select>
<select id="form_subselect_1">
<option value="A">A</option>
<option value="B">B</option>
<option value="C">C</option>
<option value="D">D</option>
</select>
</form>
Follow-up:
Added vue method (below) for how I'm currently adding Vuejs models to the Django Model Formsets. Question: Is there a better way?
addForm: function () {
this.count++
let form_count = this.count
form_count++
let formID = 'id_form-' + this.count
incremented_form = this.vue_form.replace(/form-\d/g, 'form-' + this.count)
this.formList.push(incremented_form)
this.$nextTick(() => {
let total_forms = document.getElementsByName('form-TOTAL_FORMS').forEach
(function (ele, idx) {
ele.value = form_count
})
})
},
As stated above this was my final answer due to no response:
addForm: function () {
this.count++
let form_count = this.count
form_count++
let formID = 'id_form-' + this.count
incremented_form = this.vue_form.replace(/form-\d/g, 'form-' + this.count)
this.formList.push(incremented_form)
this.$nextTick(() => {
let total_forms = document.getElementsByName('form-TOTAL_FORMS').forEach
(function (ele, idx) {
ele.value = form_count
})
})},
I have the following HTML code:
<select id="select1">
<option value="0">Option 0</option>
<option value="1">Option 1</option>
<option value="2">Option 2</option>
<option value="3">Option 3</option>
</select>
<select id="select2">
<option value="0">Option 0</option>
<option value="1">Option 1</option>
<option value="2">Option 2</option>
<option value="3">Option 3</option>
</select>
<select id="select3">
<option value="0">Option 0</option>
<option value="1">Option 1</option>
<option value="2">Option 2</option>
<option value="3">Option 3</option>
</select>
<input type="text" id="select4">
I am turning them into Select2 elements and I am changing the INPUT to be a SELECT and afterwards a Select2 as follow:
$(function() {
$('#select1').select2();
$('#select2').select2();
var field_value = $('#select2 :selected').val();
var module = $('#select1 :selected').val();
$('#select3').select2().on('select2:select', function(ev) {
var condition_type = $(this).val();
var select_el = '<select id="select4" style="width: 75%" multiple="multiple"></select>';
$('#select4').replaceWith(select_el);
$('#select4').select2({
placeholder: 'Start typing ...',
tags: true,
ajax: {
delay: 200,
url: '/someUrl',
minimumInputLength: 2,
data: function(params) {
var query = {
keyword: params.term,
condition: condition_type,
field: field_value,
table_name: module
}
return query;
},
processResults: function (data) {
return {
results: data
};
}
}
});
});
});
This is currently working without any problem. As soon as I sent the AJAX call the values of #select1, #select2 are being sent as a REQUEST parameter that's OK but if I change the values of #select1, #select2 and try the same AJAX request the previous values are sent and not the new ones.
I have tried the following but is not working:
$('select#conditions').select2().on('select2:select', function (ev) {
var condition_type = $(this).val();
...
}).on('select2:selecting', function (ev) {
field_value = $('#select2 :selected').val();
module = $('#select1 :selected').val();
});
So my question is how do I catch the new values? Any help? I have tried to setup a Fiddle example here but I couldn't make it to work with the AJAX call.
just simply move
var field_value = $('#select2 :selected').val();
var module = $('#select1 :selected').val();
inside
data: function(params) {
like this:
data: function(params) {
var field_value = $('#select2 :selected').val();
var module = $('#select1 :selected').val();
var query = {
keyword: params.term,
condition: condition_type,
field: field_value,
table_name: module
}
return query;
},
in this case you will always retrieve and send fresh params
I have have following selections:
<select id="custom-headers" multiple="multiple" class="searchable custom-headers">
<option data-invoice-number="36655" value="1187">RAPCY3</option>
<option data-invoice-number="87172" value="1188">1188</option>
<option data-invoice-number="79190" value="1189">CXETHD</option>
<option data-invoice-number="24584" value="1190">ZDAC2X</option>
<option data-invoice-number="49694" value="1191">2T8SRJ</option>
<option data-invoice-number="11290" value="1192">XDCH5J</option>
<option data-invoice-number="96188" value="1193">83EYS8</option>
<option data-invoice-number="33819" value="1194">WE5PEW</option>
<option data-invoice-number="56529" value="1195">CJEQWM</option>
<option data-invoice-number="55643" value="1196">RAPCY3</option>
<option data-invoice-number="72334" value="1197">1197</option>
<option data-invoice-number="14563" value="1198">CXETHD</option>
<option data-invoice-number="58963" value="1199">ZDAC2X</option>
<option data-invoice-number="44810" value="1200">2T8SRJ</option>
<option data-invoice-number="88482" value="1201">XDCH5J</option>
<option data-invoice-number="9731" value="1202">83EYS8</option>
<option data-invoice-number="41170" value="1203">WE5PEW</option>
<option data-invoice-number="1911" value="1204">CJEQWM</option>
</select>
I need to gather up both the values and invoice-number into one array..
jQuery works fine only for Reslist:
o.reservations = [];
$('.custom-headers option:selected').each(function (i, selected) {
o.reservations[i] = $(selected).val();
});
Giving me back an array of 1187, 1188, 1189 i need something like
reslist => 1187, 1188, 1189, invoices => 36655, 87172, 79190
Tried:
o.reservations = [];
$('.custom-headers option:selected').each(function (i, selected) {
o.reservations[i] = $(selected).val();
o.reservations[i] = $(selected).data('invoice-number');
});
Not sure how to define the keys in js?
$('.custom-headers option:selected').each(function (i, selected) {
o.reservations.push({
value: $(selected).val(),
number: $(selected).data('invoice-number')
});
});
This will populate the following array:
[{value: 1187, number: 36655}, {value: 1188, number: 87172}, ...]
var arr = {"reslist":[], "invoices":[]};
$('.custom-headers option:selected').each(function (i, selected) {
arr.reslist.push($(this).val());
arr.invoices.push($(this).data("invoice-number"));
});
Use map.
console.log($('#custom-headers option').map(function(option){
var $this = $(option);
return { invoice-number: $this.data('invoice-number'), value: $this.val() };
}));
I am using the SumoSelect dropdown for multiselect options. But i cannot get the selected values array.
Below the sample code :
<script type="text/javascript">
$(document).ready(function () {
window.testSelAll = $('.testSelAll').SumoSelect({okCancelInMulti:true, selectAll:true });
$('.btnOk').on('click', function(){
var obj = [];
$('option:selected').each(function () {
obj.push($(this).index());
alert("Selected Values=="+$(this).val());
});
for (var i = 0; i < obj.length; i++) {
$('.testSelAll')[0].sumo.unSelectItem(obj[i]);
}
});
});
</script>
<select multiple="multiple" placeholder="Share Your Friends" onchange="console.log($(this).children(':selected').length)" class="testSelAll">
<option value="1">Volvo</option>
<option value="2">Saab</option>
<option value="3">Mercedes</option>
<option value="audi">Audi</option>
<option value="bmw">BMW</option>
<option value="porsche">Porche</option>
<option value="ferrari">Ferrari</option>
<option value="mitsubishi">Mitsubishi</option>
</select>
If you want the selected values instead of the text, just change .text() to .val().
If you want to get the array, see below with working example at the bottom.
jQuery
$(document).ready(function() {
$('.testSelAll').SumoSelect({
okCancelInMulti: true,
selectAll: true
});
$('.btnOk').on('click', function() {
var obj = [],
items = '';
$('.testSelAll option:selected').each(function(i) {
obj.push($(this).val());
$('.testSelAll')[0].sumo.unSelectItem(i);
});
for (var i = 0; i < obj.length; i++) {
items += ' ' + obj[i]
};
alert(items);
});
});
HTML
<select multiple="multiple" class="testSelAll">
<option value="car1">Volvo</option>
<option value="car2">Saab</option>
<option value="car3">Mercedes</option>
<option value="car4">Audi</option>
</select>
Working JSFIDDLE
You can get them from underlying hidden select element.
using jquery eg.
$('.select1 option:selected')
I think the cleanest way to do this. Is to take advantage of html5 select element underlying SumoSelect.
HTML
<select multiple="multiple" class="testSelAll" id="multi-select">
<option value="car1">Volvo</option>
<option value="car2">Saab</option>
<option value="car3">Mercedes</option>
<option value="car4">Audi</option>
</select>
Javascript
var values = $('#multi-select').val();
This line will return a string list of the values selected.