Clone or Add more fields using jquery including the functionality - javascript

So I have a select group of reason and other select-group for subreason. I want to add more reason but as soon as I click on the button the same field appear but it changes the value of above fields too. I need them to be independent but also perform the (reason -subreason).
Code
<div class="tab" id="add_reason">
<h4 class="card-title">Reason</h4><Br>
<label for="roads">Select Branch</label>
<select name="reason[]" id="reason" class="form-control required">
<option value="">Reasons</option>
<option class="road" value="Road">Road</option>
<option class="driver" value="Driver">Driver's Fault</option>
</select><br>
<select id="subreason" name="subreason[]" class="form-control">
<optgroup label="Road" required>
<option>Pot Holes</option>
<option>No boards at starting and ending point of Bridge</option>
<option>No Painting to Divider</option>
<option>Speed Breaker without Zebra Crossing</option>
</optgroup>
<optgroup label="Driver" required>
<option>Lane Cutting</option>
<option>Overtaking from Wrong side</option>
<option>Corner Overtaking</option>
</optgroup>
</select>
<button type="button" class="btn btn-primary" id="btn-reason">Add Reasons</button>
</div>
Script
$(document).ready(function(){
var $optgroups = $('#subreason > optgroup');
$("#reason").on("change",function(){
var selectedVal = this.value;
$('#subreason').html($optgroups.filter('[label="'+selectedVal+'"]'));
});
});
$(document).ready(function(){
$("#btn-reason").click(function(){
$('#add_reason').clone(true).appendTo('#add_reason');
});
});

The first thing to know about jQuery .clone() is that it creates new DOM elements from some existing ones.
That implies the same rules as any other dynamically created elements:
Do not use ids
Delegate event handlers
Additionnally, the cloned set of elements cannot be appended multiple places... So, to use it as a templating trick, you have to clone twice. Once on page load (to save them before any change occurs) and once again when appending somewhere.
$(document).ready(function() {
// Cloned "templates"
let reason_wrapper = $(".reason-wrapper").clone()
var $optgroups = $(".subreason > optgroup").clone()
// "delegated" event handler for any existing or future .reason element
$(document).on("change", ".reason", function() {
var selectedVal = this.value;
$(this)
.closest(".reason-wrapper")
.find(".subreason")
.html($optgroups.clone().filter('[label="' + selectedVal + '"]'));
});
// "delegated" event handler for any existing or future .btn-reason element
$(document).on("click", ".btn-reason", function() {
reason_wrapper.clone().appendTo("#add_reason");
});
});
.reason-wrapper {
margin-top: 1em;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="tab" id="add_reason">
<h4 class="card-title">Reason</h4>
<div class="reason-wrapper">
<label for="roads">Select Branch</label>
<select name="reason[]" class="reason form-control required">
<option value="">Reasons</option>
<option class="road" value="Road">Road</option>
<option class="driver" value="Driver">Driver's Fault</option>
</select>
<br>
<select name="subreason[]" class="subreason form-control">
<optgroup label="Road" required>
<option>Pot Holes</option>
<option>No boards at starting and ending point of Bridge</option>
<option>No Painting to Divider</option>
<option>Speed Breaker without Zebra Crossing</option>
</optgroup>
<optgroup label="Driver" required>
<option>Lane Cutting</option>
<option>Overtaking from Wrong side</option>
<option>Corner Overtaking</option>
</optgroup>
</select>
<button type="button" class="btn btn-primary btn-reason">Add Reasons</button>
</div>
</div>

Related

Remove error text when input is unlocked in jquery

I have a form with a select, input and a function that locks my input when an option is selected.
I added a warning that inputs are locked when someone selects an option. I would like to add a function to remove this warning when someone chooses an option with value="".
It's removing my warning but for example when I choose option text 1 then text 2 my warning displays twice and then when I choose a selection with first option it removes warning but only first.
How to change it so that the warning displays only once, and not more times, and removes it after select with option first.
$(function() {
$('#stato').change(function() {
var value = $(this).val(); //Pobranie wartości z tego selecta
if (value == "") {
$('#data_consegna').prop('disabled', false);
$("#error").remove();
} else {
$('#data_consegna').prop('disabled', true);
$('#data_consegna').after('<div id="error" style="color:red;">Input locked</div>');
}
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.0/jquery.min.js"></script>
<div class="col-4">
<label>Enabled </label>
<select name="stato" id="stato" class="form-control">
<option value="">Choose</option>
<option value="Text1">Text1</option>
<option value="Text2">Text2</option>
<option value="Text3">Text3</option>
<option value="Text4">Text4</option>
</select>
</div>
<div class="col-4">
<label>Disabled when choose option in select</label>
<input id="data_consegna" type="text" class="form-control" name="data_consegna" placeholder="Data Consegna" />
</div>
my warning displays twice
You don't check if it's already there or remove it.
removes only first
IDs must be unique, so $("#error").remove(); will only remove the first one. Use classes instead of IDs to remove multiple elements. If you only add once, this would not be an issue; just explaining why it removes only the first.
As noted in the other answer, the best solution is to simply .show()/.hide(), so I won't repeat that here.
To update your code, you can always remove the error, then add it back if needed - this isn't the most efficient as noted above.
Updated snippet:
$(function() {
$('#stato').change(function() {
var value = $(this).val(); //Pobranie wartości z tego selecta
// always remove any existing error
$("#error").remove();
if (value == "") {
$('#data_consegna').prop('disabled', false);
} else {
$('#data_consegna').prop('disabled', true);
$('#data_consegna').after('<div id="error" style="color:red;">Input locked</div>');
}
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.0/jquery.min.js"></script>
<div class="col-4">
<label>Enabled </label>
<select name="stato" id="stato" class="form-control">
<option value="">Choose</option>
<option value="Text1">Text1</option>
<option value="Text2">Text2</option>
<option value="Text3">Text3</option>
<option value="Text4">Text4</option>
</select>
</div>
<div class="col-4">
<label>Disabled when choose option in select</label>
<input id="data_consegna" type="text" class="form-control" name="data_consegna" placeholder="Data Consegna" />
</div>
Also note, as it's using an ID, it can only be used for a single error message.
The simple way to achieve what you require is to have the notification div always contained in the DOM, but hidden, and then hide/show it depending on the state of the select, like this:
jQuery(function($) {
$('#stato').change(function() {
var value = $(this).val();
if (value == "") {
$('#data_consegna').prop('disabled', false);
$("#error").hide();
} else {
$('#data_consegna').prop('disabled', true);
$('#error').show();
}
});
});
#error {
color: red;
display: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.0/jquery.min.js"></script>
<div class="col-4">
<label>Enabled </label>
<select name="stato" id="stato" class="form-control">
<option value="">Choose</option>
<option value="Text1">Text1</option>
<option value="Text2">Text2</option>
<option value="Text3">Text3</option>
<option value="Text4">Text4</option>
</select>
</div>
<div class="col-4">
<label>Disabled when choose option in select</label>
<input id="data_consegna" type="text" class="form-control" name="data_consegna" placeholder="Data Consegna" />
<div id="error">Input locked</div>
</div>

How can I dynamically update materialize <select>?

I have a select tag with several options. I am using materizlizecss select, and I would like to use javascript to disable certain options based on certain conditions. I have read another post on how to do this, but I need to do it without jquery. When I try it, nothing happens. No errors or warnings in the console either.
<form id="code-form">
<h4 style="color: black;">Generate Code</h4>
<div class="input-field">
<select name="security-select" id="security-select">
<option style="display: none;" id="webmaster-value" value="1">Webmaster</option>
<option id="scoutmaster-value" value="2">Scoutmaster</option>
<option id="general-admin-value" value="3">General Admin</option>
<option id="spl-value" value="4">Senior Patrol Leader</option>
<option selected id="standard-user-value" value="5">Standard User</option>
</select>
</div>
<button class="btn deep-purple" id="add-code">Generate Code</button>
</form>
.
if (security == '2') {
document.querySelector('#webmaster-value').setAttribute('disabled', 'disabled')
}
You have to Re-Initialize a select field after edited it
document.addEventListener('DOMContentLoaded', function () {
var elems = document.querySelectorAll('select');
var instances = M.FormSelect.init(elems);
});
document.getElementById("change-code").addEventListener("click", function () {
document.querySelector('#webmaster-value').setAttribute('disabled', 'disabled');
// Re-Initialize select
var elems = document.querySelectorAll('select');
var instances = M.FormSelect.init(elems);
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/js/materialize.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/css/materialize.min.css" rel="stylesheet" />
<form id="code-form">
<h4 style="color: black;">Generate Code</h4>
<div class="input-field">
<select name="security-select" id="security-select">
<option style="display: none;" id="webmaster-value" value="1">Webmaster</option>
<option id="scoutmaster-value" value="2">Scoutmaster</option>
<option id="general-admin-value" value="3">General Admin</option>
<option id="spl-value" value="4">Senior Patrol Leader</option>
<option selected id="standard-user-value" value="5">Standard User</option>
</select>
</div>
<button type="button" class="btn deep-purple" id="change-code">Press to disable</button>
</form>

How to get the selected text of options in multiple select?

I am trying to get the selected option in multiple select, I can get the value in the form of an array, but I can't get the text of the option.
$(function() {
$('#sizeAddCategory').change(function(e) {
var selected = $(e.target).text();
console.log("selected " + selected);
$('#textAreaAddCategory').val(selected.join(','));
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="form-group col-sm-6">
<label for="sel1">Select Sizes (hold ctrl or shift (or drag with the mouse) to select more than one):</label>
<br/>
<select required class="form-control" id="sizeAddCategory" multiple>
<option value="1">one</option>
<option value="2">two</option>
<option value="3">three</option>
<option value="4">four</option>
</select>
</div>
<div class="form-group col-md-3">
<label for="name">Selected Sizes</label>
<br/>
<textarea required disabled rows="4" class="form-control" id="textAreaAddCategory"></textarea>
</div>
On $(e.target).text(), I am getting all the options text, I need the text of only selected options, so I can display it in the textarea.
Using .text() on a select will give the text of the control - i.e. all of the options, not just the selected ones.
To get the selected text (not value as you pointed out you can already get), you can use:
$(this).find("option:checked").map((i,e)=>$(e).text()).toArray();
Here, $(this).find("option:checked") will give you the option elements that have been selected while the .map will return the .text() for each of those values into a jquery array, with .toArray() to convert to a normal js array.
$(function() {
$('#sizeAddCategory').change(function() {
var selected = $(this).find("option:checked").map((i,e)=>$(e).text()).toArray();
console.log("selected", selected);
$('#textAreaAddCategory').val(selected.join(','));
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="form-group col-sm-6">
<label for="sel1">Select Sizes (hold ctrl or shift (or drag with the mouse) to select more than one):</label>
<br/>
<select required class="form-control" id="sizeAddCategory" multiple>
<option value="1">one</option>
<option value="2">two</option>
<option value="3">three</option>
<option value="4">four</option>
</select>
</div>
<div class="form-group col-md-3">
<label for="name">Selected Sizes</label>
<br/>
<textarea required disabled rows="4" class="form-control" id="textAreaAddCategory"></textarea>
</div>
It's because the target that you're defining is in the select tag. Instead of using:
$('#sizeAddCategory').change(function(e) {
use:
$('.option-category').click(function(e) {
and add a class in the options:
<option value="{{$size->id}}" class="option-category">{{$size->name}}</option>
you write :
var selected = $(e.target).text();
you should get the value of selectbox and
you should write
var selected = $(e.target).val();
oh my god
i right now understand what did you mean
ok
write :
$("#selectBox").change(function(e){
var x = $(e.target).find("option:checked").text();
console.log(x);
});

Passing dynamic values to a jQuery Plugin

The jQuery plugin is looking for some value to set:
$('.toClone_example88888').metalClone({
position:'after',
btnClone : '.btn_toClone_example88888'
});
The problem is the class names for the item to be cloned, and the corresponding button will be coming from a database so the values need to be dynamic.
I've tried this and while it did not work, it did not produce any console errors either. What am I missing or is this even possible to do?
I found this SO question and believe it has the same core components (Sending dynamic variable to jquery) but applying those same concepts didn't work with my implementation.
$('.cloneBtn').on('click', function(){
var getDestinationOfWhereClonedCopyShouldGo = $(this).data("destinationclone");
$('#' + getDestinationOfWhereClonedCopyShouldGo).metalClone({
position:'after',
btnClone : '.cloneBtn'
});
});
I also tried this but same this, didn't work but no error message either:
var cloneThis = function(){
$('.cloneBtn').on('click', function(){
var getDestinationOfWhereClonedCopyShouldGo = $(this).data("destinationclone");
putCloneHere(getDestinationOfWhereClonedCopyShouldGo);
});
}
var putCloneHere = function(element){
$('#' + element).metalClone({
position:'after',
btnClone : '.cloneBtn'
});
}
Additional HTML as requested:
<div id="firstOne">
<input type="text">
<select id="m">
<option value="">--Please Select</option>
<option value="Hello">Hello</option>
</select>
</div>
<div class="container_body">
<input type="button" class="cloneBtn" value="Create New Copy" data-destinationclone="firstOne">
</div>
<div id="secondOne">
<input type="text">
<select id="m">
<option value="">--Please Select</option>
<option value="Hello">Hello</option>
</select>
</div>
<div class="container_body">
<input type="button" class="cloneBtn" value="Create New Copy" data-destinationclone="secondOne">
</div>
Here is a jsfiddle (which includes the plugin code).

"Add" button stops working after deleting rows

I'm able to clone the #ingredient_1 div with the Add button. However, after pressing Add several times, then deleting random cloned divs with their specific X buttons, the Add button stops working.
I've replicated this problem across several browsers. Any advice would go a long way.
$('#add_more').click(function() {
var num = $('.clone').length;
var newNum = num + 1;
var newElem = $('#ingredient_1').clone().attr('id', 'ingredient' + '_' + newNum);
$('#ingredient_' + num).after(newElem);
});
$('#main').on('click', '.remove', function() {
$(this).parent().remove();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="main">
<div id="ingredient_1" class="clone">
<select id="1">
<option selected="selected">Please Select</option>
<option value="">Select</option>
<option value="">Select</option>
<option value="">Select</option>
<option value="">Select</option>
</select>
<input type="text" name="name" placeholder="Amount" />
<select id="2">
<option selected="selected">Units</option>
<option value="">Select</option>
<option value="">Select</option>
<option value="">Select</option>
<option value="">Select</option>
</select>
<select id="3">
<option selected="selected">Time</option>
<option value="">Select</option>
<option value="">Select</option>
<option value="">Select</option>
<option value="">Select</option>
</select>
<button class="remove">X</button>
</div>
<div id="add_button">
<input type="button" id="add_more" value="Add" />
</div>
</div>
Once you delete the first row the element you're cloning no longer exists. Clone the element outside your click function so it's not overwritten:
var newElem = $('#ingredient_1').clone().attr('id', 'ingredient' + '_' + newNum);
var num = 1;
$('#add_more').click(function() { ... });
Also, declare your ID incrementor outside the function and simply add 1 each time the click function runs with num++. I'm guessing that it doesn't really matter what the ID values are, so as long as they're unique this works.
The problem is that you're using .length to calculate newNum. If you delete DIVs in the middle, you'll end up with duplicate IDs. For instance, suppose you first add 3 DIVs, you'll have DIVs numbered 1, 2, 3, 4. Then you delete #3. The next time you click Add, $(".clone").length will be 3, so you'll set newNum = 4;. But there's still a DIV with that ID.
Instead of using $(".clone").length, get the ID of $(".clone:last"), get the number at the end of it, and add 1 to that.
You're cloning, which if you have at least one static item, is fine. I fixed up your code so your initial row is hidden, and you have an ID variable that is auto incremented. On top of which, on load, it creates clones and creates the first row. Your back end code will just have to ignore a case where the style is set to display:none.
var id = 1;
$(function () {
var first = $('.clone');
first.attr('style', 'display:none');
NewRow();
});
$('#add_more').click(function () {
NewRow();
});
function NewRow() {
console.log('num = ' + id++);
var newElem = $('.clone:last').clone().attr('id', 'ingredient' + '_' + id + '_x');
newElem.attr('style', '');
$('.clone:last').after(newElem);
}
$('#main').on('click', '.remove', function () {
$(this).parent().remove();
});
You'll notice that I changed your click event to call the function NewRow(), this was done so that you can call a function in the Document.Ready event, as well as on the button click.
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="main">
<div id="ingredient_1" class="clone">
<select id="1">
<option selected="selected">Please Select</option>
<option value="">Select</option>
<option value="">Select</option>
<option value="">Select</option>
<option value="">Select</option>
</select>
<input type="text" name="name" placeholder="Amount" />
<select id="2">
<option selected="selected">Units</option>
<option value="">Select</option>
<option value="">Select</option>
<option value="">Select</option>
<option value="">Select</option>
</select>
<select id="3">
<option selected="selected">Time</option>
<option value="">Select</option>
<option value="">Select</option>
<option value="">Select</option>
<option value="">Select</option>
</select>
<button class="remove">X</button>
</div>
<div id="add_button">
<input type="button" id="add_more" value="Add" />
</div>
</div>
Working JSFiddle is here

Categories