JQuery hide/show div based on select options - javascript

JQuery noob here, I'm trying to make appear/disappear divs depending on multiple form select options.
My problem is that the div hide successfully, but I can't manage to make them appear back again when an option is selected.
Here is my JQuery code
<script type="text/javascript">
$(document).ready(function () {
$('#areaFields').hide();
$('#areaItems').hide();
$('#areaPartners').hide();
$('#hidden3').hide();
$('#items').hide();
$('#partners').hide();
$('#fields').hide();
$('#hidden2').hide();
$('#block').hide();
$('#ORDER').hide();
$('#type').change(function () {
$('#ORDER').hide();
$('#' + $(this).val()).show();
});
});
</script>
and here is my HTML
<div class="container">
<div class="content-section">
<form method="POST" action="">
{{ form.hidden_tag() }}
<fieldset class="form-group">
<legend class="border-bottom mb-4">Customizing</legend>
<div class="container">
<div class="form-group default1">
<div class="row">
<div class="col">
<div id="taille" class="form-group">
{{ form.tailleDocX.label }}
{{ form.tailleDocX }}
{{ form.tailleDocY.label }}
{{ form.tailleDocY }}
</div>
</div>
</div>
<div class="row">
<div class="col">
<div id="type" class="form-group">
{{ form.type.label }}
{{ form.type }}
</div>
</div>
<div class="col">
<div id="customer" class="form-group">
{{ form.customer.label }}
{{ form.customer }}
</div>
</div>
</div>
</div>
<div id="ORDER" class="form-group">
<hr>
<div class="row">
<div class="col">
<div id="block" class="form-group">
{{ form.block.label }}
{{ form.block }}
</div>
</div>
</div>
<div id="hidden2" class="form-group">
<hr>
<div class="row">
<div class="col">
<div id="items" class="form-group">
{{ form.itemsFields.label }}
{{ form.itemsFields }}
</div>
<div id="partners" class="form-group">
{{ form.partnersFields.label }}
{{ form.partnersFields }}
</div>
<div id="fields" class="form-group">
{{ form.fields.label }}
{{ form.fields }}
</div>
</div>
</div>
</div>
<div id="hidden3" class="form-group">
<hr>
<div class="row">
<div class="col">
<div id="areaFields" class="form-group">
{{ form.areaFields }}
</div>
<div id="areaItems" class="form-group">
{{ form.areaItems }}
</div>
<div id="areaPartners" class="form-group">
{{ form.areaPartners }}
</div>
</div>
</div>
</div>
<div class="form-group default2">
<hr>
<div class="row">
<div class="col">
{{ form.submit }}
</div>
</div>
</div>
</div>
</div>
</fieldset>
</form>
</div>
To create the form I'm using WTForm from FLASK, if needed here is the code :
class AreaFields(FlaskForm):
area1 = IntegerField("X0")
area2 = IntegerField("X1")
area3 = IntegerField("Y0")
area4 = IntegerField("Y1")
textArea = StringField("Texte")
class AreaItems(FlaskForm):
name = StringField("Name")
class AreaPartners(FlaskForm):
area1 = IntegerField("X0")
area2 = IntegerField("X1")
area3 = IntegerField("Y0")
area4 = IntegerField("Y1")
rolePartners = SelectField("Role", id="role")
class AjouterForm(FlaskForm):
type = SelectField("Type",
choices=[("INVOICE", "invoice"), ("ORDER", "order"), ("SERVICE_REQUEST", "service_request")],
id="type")
block = SelectField("Block", choices=[("ITEMS", "items"), ("PARTNERS", "partners"), ("fields", "fields")],
id="block")
itemsFields = SelectField("Champs", id="items")
partnersFields = SelectField("Champs", id="partnersFields")
fields = SelectField("Champs", id="fields")
tailleDocX = IntegerField("Taille X", validators=[DataRequired()])
tailleDocY = IntegerField("Taille Y", validators=[DataRequired()])
customer = SelectField("Customer", choices=[("NotFinalData", "NotFinalData")])
areaFields = FormField(AreaFields)
areaItems = FormField(AreaItems)
areaPartners = FormField(AreaPartners)
submit = SubmitField('Voir le résumer')
For the moment what I want is : to hide all the div like I did, then show the div #ORDER if order is selected in the form, or to hide the div again if another option is selected, then I'll do the same for the others select and div once I can manage to make it work.
Thanks for reading !
Edit 1 : My first select that manage the first hide/show is form.type, it contains 3 options : INVOICE, ORDER, SERVICE_REQUEST
When I select INVOICE or SERVICE_REQUEST, everything must stay hide because thoose option aren't ready for the moment, but when I select ORDER, I wish to make appear the divs #ORDER and #block. #ORDER contains all the other divs specific to the ORDER option, #block contain another select that will make appear/disappear another div depending on the option selected.
Here is a picture to show the actual form without being hidden
The first select is Type, it must make appear Block if order is selected, and block make appear a Champs depending on the option selected.
Edit 2 : BIG NEWS, I just found out what was my problem, it's so dumb of me for not seeing this at first, I used the same ID for the div and for the WTForm select... so basicly I was checking for changement for the div and not for the select... I just feel so dumb right now, thank you for trying to help me !

You just have to hide only the element your previously showed. your code should look like this.
<script type="text/javascript">
$(document).ready(function () {
var current_element = '';
$('#areaFields').hide();
$('#areaItems').hide();
$('#areaPartners').hide();
$('#hidden3').hide();
$('#items').hide();
$('#partners').hide();
$('#fields').hide();
$('#hidden2').hide();
$('#block').hide();
$('#ORDER').hide();
$('#type').change(function () {
var id = $(this).val()
$('#' + id).show();
// hide previously showed element
if(current_element != '') $('#' + current_element).hide();
// store id of previously selected element
current_element = id
});
});
</script>

Related

How to stop all items from being opened when editing item in ngFor loop

I have an array of objects and you can edit the name of each one but then I click to edit one all of the names of the items open, I am wondering how do to fix this.
<div *ngFor="let stop of fave; let i = index" attr.data="{{stop.Type}}">
<div class="card m-1">
<div class="card-body">
<div class="card-text">
<div class="row">
<label class="name" *ngIf="!toggleName" (click)="toggleName = true">{{stop.Name}}</label>
<div class="md-form" *ngIf="toggleName">
<input (keydown.enter)="updateStopName(i, stop.id); toggleName = false" placeholder="Chnage Stop Name" [(ngModel)]="stopName" required mdbInput type="text"
id="form1" class="form-control">
</div>
</div>
<div class="custom">
<img *ngIf="stop.Type === 'Train'" class="train-icon" style="width: 40px; height:40px"
src="assets/img/icon_trian.png" />
<img *ngIf="stop.Type === 'bus'" style="width: 40px; height:40px" src="assets/img/icon_bus.png" />
<img *ngIf="stop.Type === 'Luas'" style="width: 40px; height:40px"
src="assets/img/icon_tram.png" />
</div>
<label class="col-4 custom-label">Stop</label>
<label class="col-5 custom-service-label">Service</label>
<div class="row">
<span class="col-5 stop"> {{stop.StopNo}}</span>
<span style="padding-left:31%;" class="col-6 stop"> {{stop.Type | titlecase}}</span>
</div>
<hr />
<div class="row">
<div class="panel col-7" (click)="getRealtimeInfo({stop: stop.StopNo, type: stop.Type})">
<img class="panel-realtime" src="assets/img/icon_view.png" />
</div>
<div class="panel col-5" (click)="deleteFav(stop.id, i)">
<img class="panel-remove" src="assets/img/icon_remove.png" />
</div>
</div>
</div>
</div>
</div>
</div>
I know its something to do with the index but I am not sure how to write the code to only open the one I clicked on
As you can see at the moment all of them open any help is very much appreciated
If you want to open one at a time, you can use the index and of the item and a boolean. When clicked, set the index value to toggl if it's not already assigned, else assign it null (so that we can close the opened div on same click), and then show the content you want, when toggl === i. Something like:
<div *ngFor="let stop of fave; let i = index">
<label (click)="toggl === i ? toggl = null : toggl = i">Stuff!</label>
<div *ngIf="toggl === i">
<!-- ... -->
</div>
</div>
DEMO: StackBlitz
In your component declare one array
hideme=[];
In your html
<div *ngFor="let stop of fave; let i = index" attr.data="{{stop.Type}}">
<a (click)="hideme[i] = !hideme[i]">show/hide</a>
<div [hidden]="hideme[i]">The content will show/hide</div>
</div>
You have a unique id value inside your array, then you can do it like this:
<div *ngFor="let row of myDataList">
<div [attr.id]="row.myId">{{ row.myValue }}</div>
</div>
Assign an id to your input fields and they will work fine. Right now all of them have same id.
Use this code below as an example:
In your component, create a mapping like so:
itemStates: { [uniqueId: string]: boolean } = {};
Within your on click function:
itemClicked(uniqueId: string) {
let opened: boolean = this.itemStates[uniqueId];
if (opened !== undefined) {
opened = !opened; // Invert the result
} else {
opened = true;
}
}
In your HTML:
<div *ngFor="let item of items">
<h1 (click)="itemClicked(item.uniqueId)">{{ item.name }}</h1>
<div *ngIf="itemStates[item.uniqueId] == true">
<p>This item is open!</p>
</div>
</div>
Essentially, each item in your array should have a unique identifier. The itemStates object acts as a dictionary, with each unique ID having an associated true/false value indicating whether or not the item is open.
Edit: The accepted answer to this question is very simple and works great but this example may suit those who need to have the ability to have more than one item open at once.

How to count number of classes generated using jQuery?

I have following HTML code.
Here 2 add/remove link exists. 1) Add More Details(+) 2) Add(+)
when I click on Add(+) link its clone the tour_wrap class div and counting the number of trip_counting class div cloned/added. Like: Trip 1, Tip 2, Trip 3 etc..
And, I have another link called Add More Details (+) which is clone the tour_wrap div.
So when I click on this link twice for e.g then it's clone the tour_wrap div 2 times, That's good.
Now I have 3 tour_wrap div. In this div's you can see that I have the link Add(+) 3 times, right? Yes. So when I click on any Add(+) link then it's counting the Total number of trip_counting classes added But I want to count only corresponding trip_counting classes.
Check this image:
HTML Code:
<div class="tour_wrap">
<!-- some other html code for the tour -->
<div class="trip_wrap">
<h5 class="badge badge-success trip_counting">Trip 1</h5>
<div class="col-md-4">
<div class="form-group">
<label>From</label>
<input type="text" name="ow_from[]" class="form-control" placeholder="From">
</div>
</div>
<div class="col-md-4">
<div class="form-group">
<label>To</label>
<input type="text" name="to[]" class="form-control" placeholder="To">
</div>
</div>
<div class="col-md-12">
<div class="change_trip text-right">
<a class="btn add_button_trip trip_btn">Add(+)</a>
</div>
</div>
</div> <!-- end trip_wrap -->
</div> <!-- end tour wrap -->
<div class="row">
<div class="col-md-12">
<div class="form-group change text-right">
<a class="btn add_button add_more add_more_btn"><strong>Add More Details (+)</strong></a>
</div>
</div>
</div> <!-- end row -->
jQuery Code:
// for all way
$("body").on("click",".add_button",function(){
var html = $(".tour_wrap").first().clone();
$(html).find(".change").html("<a class='btn remove remove_more'>Remove Details(-)</a>");
$(".tour_wrap").last().after(html);
$('.counting').each(function(i, elm) {
$(elm).text('Detail ' + (i + 1));
});
});
$("body").on("click",".remove",function(){
$(this).parents(".tour_wrap").remove();
});
// add more trip
$("body").on("click",".add_button_trip",function(){
var html = $(".trip_wrap").first().clone();
$(html).find(".change_trip").html("<a class='btn remove_trip remove_more trip_btn_remove'>Delete(-)</a>");
//$(".trip_wrap").last().after(html);
$('.trip_wrap').each(function(i, elm) {
$(elm).last().after(html);
});
$('.trip_counting').each(function(i, elm) {
$(elm).text('Trip ' + (i + 1));
});
});
$("body").on("click",".remove_trip",function(){
$(this).parents(".trip_wrap").remove();
});

javascript - replicate a div on button click

I have a html with various form elements:
<div class="card border-bg-light mb-3" id="card_steps">
<div class="card-header bg-transparent" id="card_header">
<span class="pull-right clickable close-icon" data-effect="fadeOut"><i class="fa fa-times"></i></span>
{{ form.non_field_errors }}
<div class="fieldWrapper">
{{ form.step_description.errors }}
<label for="{{ form.step_description.id_for_label }}">Step:</label>
{{ form.step_description }}
</div>
</div>
<div class="card-body" id="card_body">
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
<div class="fieldWrapper">
{{ form.can_edit_email.errors }}
<label for="{{ form.can_edit_email.id_for_label }}">Editable:</label>
{{ form.can_edit_email }}
</div>
<div class="fieldWrapper">
{{ form.step_notification_period.errors }}
<label for="{{ form.step_notification_period.id_for_label }}">Notify user before launch
date:</label>
{{ form.step_notification_period }}
</div>
<div class="fieldWrapper">
{{ form.step_attachment.errors }}
<label for="{{ form.step_attachment.id_for_label }}">Upload:</label>
{{ form.step_attachment }}
</div>
</form>
</div>
</div>
In my next card div i have a link Add Steps which upon clicking will create a div which is exactly the same as the div card_steps above and it will be right below the card_steps div, so how do i go about doing this in javascript?
<div class="card">
<div class="card-body">
+ Add Step
</div>
</div>
Put an onclick on your button in your html:
onclick="createClone()"
then set a method to clone a div in your js:
function createClone() {
var div = document.getElementById('div_id'),
clone = div.cloneNode(true); // true means clone all childNodes and all event handlers
clone.id = "some_id";
document.body.appendChild(clone);
}
found at this answer.
You can copy a div's INNER contents quite easily using:
document.getElementById("add_step").innerHTML
Once you have that, you essentially just cloned the INNER contents of that div. Everything. If you want the shell of the div, you will need to recreate it manually. For example, you could do this:
var x = document.getElementById("add_step"); // the clone's parent element.
var y = document.createElement("div"); // the clone's inner content
y.innerHTML = document.getElementById("card_steps").innerHTML;
x.appendChild(y);
There, you have essentially just cloned your div.
EDIT: Edited to better suit your question with correct element ID names.

Form on submit has no values

I have multiple forms on the page, they are generated with Jinja2 and Flask, each form has it's own unique id, there is a button in each form. I want to click the button and get the values of the form where the button is actually located. However, when I try to serialize the form, it is empty. All the console.log lines work fine, each button does indeed retrieve the form it is located in.
HTML:
<form id='{{ "item-"+item.articleNr }}' class="itemTemplate">
<div class="thumb">
<img style="width: 200px;height: 200px;" src="{{ url_for('static',filename='images/'+item.image) }}">
</div>
<div class="contentWrapper">
<div class="content" id="item-content">
<label id="articleNameBlock" name="articleName">{{ item.articleName }}</label>
<div class="articleNrBlock" name="articleNr">{{ item.articleNr }}</div>
<div class="eanBlock" name="ean">{{ item.ean }}</div>
<div class="articleCodeBlock" name="articleCode">{{ item.articleCode }}</div>
<div class="articleColorBlock" name="color">{{ item.Color }}</div>
<div class="priceBlock" name="price">{{ item.Price }}</div>
<div class="buttons">
<button id="addLabel" class="ui-btn ui-btn-inline btn btn-success" type="submit">Label Aanvragen</button>
</div>
</div>
</div>
</form>
JS:
$(document).ready(function(){
$('.btn-success').on('click',function(){
console.log('The addButton is clicked.');
var $form = $(this).parents('form');
var data = $form.serialize();
console.log('Form '+ $form.attr('id'));
console.log(data)
});
//when the form is submitted
$('form').submit(function (evt) {
evt.preventDefault(); //prevents the default action
});
})
I solved my problem, thanks to the hint given by CBroe, I was indeed having a wrong approach. I changed the code. Here is the solution:
HTML:
<div id='{{ "item-"+item.articleNr }}' class="itemTemplate">
<div class="thumb">
<img style="width: 200px;height: 200px;" src="{{ url_for('static',filename='images/'+item.image) }}">
</div>
<div class="contentWrapper">
<div class="content" class="itemContent">
<label class="articleNameBlock" name="articleName">{{ item.articleName }}</label>
<div class="articleNrBlock" name="articleNr">{{ item.articleNr }}</div>
<div class="eanBlock" name="ean">{{ item.ean }}</div>
<div class="articleCodeBlock" name="articleCode">{{ item.articleCode }}</div>
<div class="articleColorBlock" name="color">{{ item.Color }}</div>
<div class="priceBlock" name="price">{{ item.Price }}</div>
<div class="buttons">
<button class="ui-btn ui-btn-inline btn btn-success" type="submit">Label Aanvragen</button>
</div>
</div>
</div>
</div>
JS:
$('.btn-success').on('click',function(){
console.log('The addButton is clicked.');
var $item = $(this).closest('.itemContent');
var $elements = $item.children();
var x = $item.children('.articleNameBlock')[0].innerHTML;
var articleName = $elements[0].innerHTML;
});
Firstly I would change the
var $form = $(this).parents('form');
to
var $form = $(this).closest('form');
as parents() traverses the DOM and selects all matching elements.
Secondly I'd change the
$('form').submit(function (evt)
to
$(document).on("submit", "form", function()
to make sure form elements are correctly selected.
I would also check my html if it is well-formed, a form tag inside a form tag doesn't work.

Using AngularJS to show divs based on select value

I'm trying to use an HTML select element's value to show or hide certain div tags with AngularJS. Here is my code:
<body ng-app="kiosk" id="ng-app" >
<div class="page" ng-controller="kiosk-controller" ng-cloak="true">
<section class="signin">
<div class="intro">
<h1 id="service-desk-name">{{servicedeskname}}</h1><br></br>
<h4 id="welcome">{{welcome}}</h4>
</div>
<hr></hr>
<form id="form" name="form">
<div>
<label>Do you have an ID?</label><br></br>
<select type="select"
ng-model="user.affiliated"
ng-required="true"
ng-options="opt as opt.name for opt in affiliate.affiliateOptions">
<option value="">--Select an answer--</option>
</select>
</div>
<div ng-switch="user.affiliated">
<div ng-switch-when="Yes">
<!--><-->
</div>
<div ng-switch-when="No">
<!--><-->
</div>
</div>
And here is the Javascript snippet:
var kiosk = angular.module('kiosk',[]);
kiosk.controller('kiosk-controller', ['$scope', function($scope, $user) {
$scope.servicedeskname = 'Service Desk';
$scope.welcome = 'Please sign in and a consultant will be with you shortly.';
$scope.affiliate = {affiliateOptions:[]};
$scope.affiliate.affiliateOptions = [
{ name: 'Yes' },
{ name: 'No' }
];
/*other stuff*/
};
I can't figure out the proper way to reference the select options in the HTML tags using ng directives. Unless it's not super clear, I want to be able to show one div if the select value is "Yes", and show another if the select value is "No".
I think the switch statement you use need small modification
<div ng-switch on="user.affiliated">
<div ng-switch-when="Yes">
<!--><-->
</div>
<div ng-switch-when="No">
<!--><-->
</div>
</div>
check this ng-switch documentation for more help
I believe you're looking for ng-show and ng-hide.
<div ng-show="user.affiliated === 'Yes'"></div>
<div ng-show="user.affiliated === 'No'"></div>
And try changing this line to this:
ng-options="opt.name as opt.name for opt in affiliate.affiliateOptions">
You forgot the name property in the switch statement.
- <div ng-switch="user.affiliated">
+ <div ng-switch="user.affiliated.name">
As can be viewed in jsfiddle
you just have a little mistake. you must have user.affiliated.name instead of user.affiliated
like this
<div ng-switch="user.affiliated.name">
<div ng-switch-when="Yes">
yes
</div>
<div ng-switch-when="No">
no
</div>
</div>

Categories

Resources