I have a HTML someting like this. In this html, number of tr is not certain. It could be 1 or 1000. Every row has a button has a name, "apply". And i have a jquery to handle click operation but in this case, jquery recognizes only first row's button. But i dont know how to do.
<tr id="jobs" th:each="job : ${job}">
<p id="jobID" th:text="${job.jobId}" style="display: none"></p>
<div class="col-md-3" id="JobTitle">
<span class="label label-default">Job Title</span>
<td th:text="${job.jobTitle}" />
</div>
<div class="col-md-3" id="jobDescription">
<span class="label label-primary">Job Description</span>
<td th:text="${job.jobDescription}" />
</div>
<div class="col-md-3" id="numberOfPersonToHire">
<span class="label label-success">Number Of Candidates</span>
<td th:text="${job.numberOfPersonToHire}" />
</div>
<div class="col-md-2" id="lastApplicationDate">
<span class="label label-info">Last Date</span>
<td th:text="${job.lastApplicationDate}" />
</div>
<button id="apply" type="submit" class="btn btn-xs"aria-label="Left Align">
<img th:src="#{/images/apply.png}" height="20" width="auto" />
Apply
</button>
</tr>
JS
$("#apply").click(function(e){
e.preventDefault();
e.stopPropagation();
debugger
var jobId = $('#jobID').text();
document.location.href = "/admin";
});
An id (declared using #) is a unique element that can't be used more than once. JavaScript identifies the first element with that specific id and doesn't continue afterwards. You might want to think about using a class:
...
<button class="apply" type="submit" class="btn btn-xs"aria-label="Left Align">
<img th:src="#{/images/apply.png}" height="20" width="auto" />
Apply
</button>
...
And then iterate through every element with the class "apply", assuming you are using JQuery:
$('.apply').each(function() {
...
});
Same thing goes for your #jobId, which can't be used more than once, so you could not use your assignment in the each-loop. You could also include a counter into your for-loop, which you could append to the ids so you would end up with something like <button id="apply-1">... or similiar. However, you would have to use selectors to find each <button> child of each <tr> element you have.
Related
I'm looking to make a table with 7-10 row and 2 columns. 1 Column for buttons and 1 column for text.
Upon clicking the button in a specific row, it will then toggle from 1 block of text to another block of text in that same row.
Example of the HTML:
<table>
<tbody>
<tr>
<td>
<a class="button1" href="#">Reveal Tips</a>
</td>
<td>
<div class="textshown1">
<p>Text being initially displayed</p>
</div>
<div class="texthidden1" style="display: none;">
<p>Text to be displayed after onclick funtion</p>
</div>
</td>
</tr>
<tr>
<td>
<a class="button2" href="#">Reveal Tips</a>
</td>
<td>
<div class="textshown2">
<p>Text being initially displayed</p>
</div>
<div class="texthidden2" style="display: none;">
<p>Text to be displayed after onclick funtion</p>
</div>
</td>
</tr>
</tbody>
</table>
and Jquery:
$('.button1').on('click', function() {
$('.textshown1').hide(0);
$('.texthidden1').show(0);
});
$('.button2').on('click', function() {
$('.textshown2').hide(0);
$('.texthidden2').show(0);
});
I'm looking for a cleaner way of accomplishing this without having to make a separate onclick function for each button/row.
Can anybody give a suggestion? Thanks.
You can use data attributes to add id on each button and textshown and texthidden elements. Then, you can simply find those div elements using jQuery like below-
jQuery('.reveal-button').click(function (e) {
let id = $(this).data("id");
jQuery(".textshown[data-id="+id+"]").toggle();
jQuery(".texthidden[data-id="+id+"]").toggle();
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table>
<tbody>
<tr>
<td>
<a class="reveal-button" data-id="1" href="#">Reveal Tips</a>
</td>
<td>
<div class="textshown" data-id="1">
<p>Text being initially displayed</p>
</div>
<div class="texthidden" data-id="1" style="display: none;">
<p>Text to be displayed after onclick funtion</p>
</div>
</td>
</tr>
<tr>
<td>
<a class="reveal-button" data-id="2" href="#">Reveal Tips</a>
</td>
<td>
<div class="textshown" data-id="2">
<p>Text being initially displayed</p>
</div>
<div class="texthidden" data-id="2" style="display: none;">
<p>Text to be displayed after onclick funtion</p>
</div>
</td>
</tr>
</tbody>
</table>
Another way to do this can be by traversing through the DOM using [parent][1] and next selectors. For example-
jQuery('.reveal-button').click(function (e) {
$(this).parent().next().find('.textshown').toggle();
$(this).parent().next().find('.texthidden').toggle();
})
you can use the same class name to avoid adding the event handler multiple times. then use jquery like:
$(".reveal-button").on("click", function(e) {
$(this).parents("tr").find(".textshown").hide(0);
$(this).parents("tr").find(".texthidden").show(0);
});
all buttons will have 'reveal-button' class and on click of that, find the ascendant tr node of the clicked button, then find the descendant div (with specific class name) of the tr node then hide/show the div.
In case the rows are dynamically generated then change the event subscription call to:
$("table").on("click", ".reveal-button", function(e) {
Given some html, a form named InterfacesIx and a button named addInterfacesIx
<div class="step-new-content white-text">
<p class="text-monospace"><small>helps you rollout a configlet about blahblah</small></p>
<form name="InterfacesIx">
<div class="row">
<div class="md-form col-12">
<input type="text" name="xxx" class="form-control white-text" placeholder="123"><label for="xxx">asn</label>
</div>
<div class="md-form col-12">
<textarea name="yyy" class="md-textarea form-control white-text" rows="3"></textarea><label for="yyy">notes</label>
</div>
</div>
<br><br><br>
</form>
<div class="col-12 text-center">
<button type="button" name="addInterfacesIx" class="btn btn-block btn-flat"><i class="fas fa-plus"></i></button>
</div>
</div>
I would like to clone/duplicate the form when the user clicks on the addInterfacesIx button using jQuery I guess.
The jQuery that I am trying looks like this:
<script>
$(document).ready(() => {
$('addInterfacesIx').click(function(){
$('InterfacesIx').clone().insertBefore('addInterfacesIx');
});
});
</script>
When I do console.log($('InterfacesIx')); nothing gets printed out. Is the selector wrong ?
When inspecting the form element on the browser I get:
copy attribute shows name="InterfacesIx"
copy selector path shows #stepper-navigation > li > div.step-new-content.white-text > form
copy xml shows //*[#id="stepper-navigation"]/li/div[2]/form
Would you be so kind to advise what I am doing wrong and how to achieve the desired result ?
Your selector $('addInterfacesIx') is not valid. If you want to grab an element by name you should use attribute selector, something like this: $( "form[name='addInterfacesIx']"). However, as mentioned before, grabbing element by class or ID is definitely better.
$('addInterfacesIx') and $('InterfacesIx') aren't valid selectors. I'd suggest putting id/class attributes on the relevant elements and then selecting them by that.
I also assume that the form elements should be siblings, as such try using insertAfter() and placing the new form after the last one currently in the DOM. Your current logic would place the new form inside the button container. Try this:
jQuery(($) => {
$('#addInterfacesIx').click(function() {
$('.interfacesIx:first').clone().insertAfter('.interfacesIx:last');
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="step-new-content white-text">
<p class="text-monospace"><small>helps you rollout a configlet about blahblah</small></p>
<form name="InterfacesIx" class="interfacesIx">
<div class="row">
<div class="md-form col-12">
<input type="text" name="xxx" class="form-control white-text" placeholder="123"><label for="xxx">asn</label>
</div>
<div class="md-form col-12">
<textarea name="yyy" class="md-textarea form-control white-text" rows="3"></textarea><label for="yyy">notes</label>
</div>
</div>
<br><br><br>
</form>
<div class="col-12 text-center">
<button type="button" name="addInterfacesIx" id="addInterfacesIx" class="btn btn-block btn-flat"><i class="fas fa-plus"></i></button>
</div>
</div>
You are confusing the fact that a name attribute is not normally used as a jQuery selector - the name attribute is normally used for keys to form values when they are submitted to the server. You can select elements using the name attribute, as indicated by the code below, but using id and class attributes is preferred.
<form id="InterfacesIx" name="InterfacesIx">
...
</form>
<div class="col-12 text-center">
<button type="button" id="addInterfacesIx" class="btn btn-block btn-flat"><i class="fas fa-plus"></i></button>
</div>
<script>
$(document).ready(() => {
$('#addInterfacesIx').click(function(){
// $('#InterfacesIx') is better
$('[name=InterfacesIx]').clone().insertBefore('addInterfacesIx');
});
});
</script>
I'm building a form in Angular2 which contains a field that is an array of objects. I've so far built the table with a Delete Row button per row and an Add Row button. These use the JavaScript push() and slice() methods.
There is a big bug though:
When adding a new row, the content of the previous rows is deleted.
That is to say, the content of the row is deleted, not the row itself.
Any ideas why?
Component Code:
public addRow(): void {
this.table.push({});
}
public deleteRow(row: object): void {
this.table.splice(this.table.indexOf(row), 1);
}
HTML Template
<form #TimesheetForm="ngForm" (ngSubmit)="saveTimesheet()">
<div class="row">
<div class="col text-right">
<button type="button" class="btn" (click)="addRow()"><i class="fa fa-plus-square" aria-hidden="true"></i> Add Row</button>
</div>
</div>
<table class="table">
<thead>
<td class="table__header">Date</td>
<td class="table__header">Time</td>
<td class="table__header">Actions</td>
</thead>
<tbody>
<tr *ngFor="let row of table">
<td class="table__item">
<input class="input" [(ngModel)]="row.date" name="date">
</td>
<td class="table__item">
<input class="input" [(ngModel)]="row.time" name="time">
</td>
<td class="table__item">
<button type="button" class="btn btn--negative" (click)="deleteRow(row)"><i class="fa fa-times" aria-hidden="true"></i> Delete</button>
</td>
</tr>
<tr *ngIf="school.rows.length == 0">
<td colspan="3">No rows exist yet. Click Add Row to start logging your timesheet.</td>
</tr>
</tbody>
</table>
</div>
<div class="row">
<div class="col">
<button class="btn btn--positive" type="submit"><i aria-hidden="true" class="fa fa-check"></i> Save</button>
</div>
<div class="col text-right">
<button class="btn btn--negative"><i aria-hidden="true" class="fa fa-times"></i> Cancel</button>
</div>
</div>
</form>
With template driven forms, we need to remember that the name attribute needs to be unique, otherwise the fields will be evaluated as the same field. So what your form does now, is not adding new form controls when you add new rows, instead it manipulates the one and same form field. If you were to put something like <pre>{{TimesheetForm.value | json}}</pre> in your template, you can see, that despite pushing new rows, there is only one form control name date and one form control named time.
So what we need to do is to provide an unique name, we can do that by using the index of the items in your table array. So do the following:
<tr *ngFor="let row of table; let i = index">
<td>
<input [(ngModel)]="row.date" name="date{{i}}">
</td>
<td>
<input [(ngModel)]="row.time" name="time{{i}}">
</td>
<!-- more code here -->
</tr>
I'm creating a toggle button to which I want to bind a select event. I've created the button, but I have no clue of how to bind the values to it and make it work like a select button. Can someone give me some clue or some examples related to it, so that I can try that out and learn some thing?
My requirement is I've to bind the select event to it and make it work like a select button.
This is how I've created the button:
<div class="row">
<div class="col-sm-6">
<div class="form-group">
<label class="col-sm-6">Tax Value</label>
<div class="col-sm-6">
<div class="input-group">
<div class="input-group-btn">
<button type="button" class="btn btn-default dropdown-toggle align-right" id="tax_toggle" name="tax_toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">Tax <span class="caret"></span></button>
</div>
<input type="text" id="invoice_request_tax_value" name="invoice_request_tax_value" class="form-control" placeholder="Tax Value" required="required" readonly="readonly">
</div>
</div>
</div>
</div>
<div class="col-sm-6">
<div class="form-group">
<label class="col-sm-12" id="invoice_request_tax_value_label">Tax Value - Nil</label>
</div>
</div>
</div>
Try using knockout.js.
This is what I am using to do the kind of action you want (binding value dynamically)
foreach-binding is the solution to your problem.
Also options-binding can be used, which you can use with select tag only.
See If you can use knockout.
create your observables then bind them per slide/toggle then u can adjust this example such that when toggled the select value in your dropdown becomes yourdropdown.selectedText (javascript) , you will notice which may seem like commented code but are actually conditional statements in ko
<tbody data-bind="foreach: yourObservableArray">
<tr data-bind="attr: { 'id': description }">
<td style="border-bottom: 1px solid #e0e0e0;">
<label data-bind="text: description"></label>
</td>
<td class="td-actions" style="border-bottom: 1px solid #e0e0e0;">
<input type="text" class="input-mini" data-bind="value: amount">
<input type="hidden" class="input-mini" data-bind="attr: { 'id': 'DC_' + description }, value: Totalcost">
</td>
<td class="toggle-soft">
<!-- ko if: description == 'Data' -->
<div id="slider" class="toggle floatright" onclick="toggleCOS()"></div>
<input type="checkbox" disabled="disabled" class="checkbx" id="cos_data" style="display: none;">
</div>
<!-- /ko -->
<!-- ko if: description != 'Data' -->
Cost
<!-- /ko -->
</td>
</tr>
</tbody>
This has got me stumped, I am testing my app on IE8 and an AJAX call is being made to the server and it is getting back a return like below. I am then doing an alert to check the output (it matches what I have below) and then it is supposed to append this to a DIV but it always fails to do this. Even if I put an alert past this line of code it still works so its not giving an error it seems, either. I figure there must be some thing with IE8 and multine-line variables or something as I am completely stumped by this, I would greatly appreciate if anyone can help.
What I am calling to append
alert(callbackReturnData)
$("#parent_tabDocumentSearch_displayMessageContents").append(
"<div id='test'>"
+ callbackReturnData + "</div>");
The contents of the callbackReturnData variable (returned from AJAX)
<div class="documentHead">
<div class="col1">
<p>
Sender: <strong><span id="dispayFileContents_sender">V Charles Weldon</span>
</strong>
</p>
<p><div id="div_subject">
Subject: <strong><span id="dispayFileContents_subject">Timesheet Revision</span>
</strong>
</div>
</p>
<p><div id="div_recipients">
Recipient: <strong><span id="dispayFileContents_recipients">Rebecca Torres</span>
</strong>
</div>
</p>
</div>
<div class="col2">
<p>
Date: <strong><span id="dispayFileContents_date"></span>12/22/2000</strong>
Rank: <strong><span id="dispayFileContents_rank"></span> </strong>
</p>
<p>
Time: <strong></strong>
</p>
<p>
Document #: <strong><span id="dispayFileContents_displayCount"></span>
</strong>
</p>
</div>
<div class="col-right">
<div class="prev-btn">
<img onclick="TabDocumentSearch_emailContentsViewNextPrev('prev')"
src="http://witnesstreefiles.s3.amazonaws.com/stable/liquis/images/prev.png"
width="25" />
</div>
<div class="next-btn">
<img onclick="TabDocumentSearch_emailContentsViewNextPrev('next')"
src="http://witnesstreefiles.s3.amazonaws.com/stable/liquis/images/next.png"
width="25" />
</div>
</div>
<div class="clear"></div>
</div>
<div class="documentBody documentBodyScroll">
I'm taking 4 hours vacation today and have updated my previous timesheet to
<br>reflect this. Please see attached.
<br>
<br>
<br>***********
<br>EDRM Enron Email Data Set has been produced in EML, PST and NSF format by ZL Technologies, Inc. This Data Set is licensed under a Creative Commons Attribution 3.0 United States License <http://creativecommons.org/licenses/by/3.0/us/> . To provide attribution, please cite to "ZL Technologies, Inc. (http://www.zlti.com)."
<br>***********
<br>Attachment: AA- Timesheet.12-16-30-00.doc type=application/msword
<br>
</div>
<div class="documentFoot">
<div class="col1">
<p style="margin-top:10px;">
Comment: <input id="tabDocumentSearch_documentCustomComment"
value="
"
name="" type="text" /> <input type=button " class="save button"
value="Save"
onclick="tabDocumentSearch_tabDocuments_updateComment()"></input>
</p>
</div>
<div class="col-right">
<div class="col1" style="margin-right:10px">
<table>
<tr>
<td style="width: 20px;" class="center"><img
src="http://witnesstreefiles.s3.amazonaws.com/stable/liquis/images/hot-btn.png"
width="20">
<div id="radioHolder_h"></div></td>
</td>
<td style="width: 20px;" class="center"><img
src="http://witnesstreefiles.s3.amazonaws.com/stable/liquis/images/priv-btn.png"
width="20">
<div id="radioHolder_p"></div></td>
</td>
<td style="width: 20px;" class="center"><img
src="http://witnesstreefiles.s3.amazonaws.com/stable/liquis/images/resp-btn.png"
width="20">
<div id="radioHolder_r"></div></td>
</td>
<td style="width: 20px;" class="center"><img
src="http://witnesstreefiles.s3.amazonaws.com/stable/liquis/images/cold-btn.png"
width="20">
<div id="radioHolder_c"></div></td>
</td>
<td style="width: 20px;" class="center">
<img src="http://witnesstreefiles.s3.amazonaws.com/stable/liquis/images/custom-btn.png" width="20">
<div id="radioHolder_cust"></div></td>
</td>
<td style="padding-top:18px;" class="center">
<select style='width:150px' class='specialHidden1' id='setCustomTagForDocument' name=''>
<option selected='selected'>Set Custom Tag</option>
<option>Priv - legal</option>
<option>Priv - spouse</option>
<option>Priv - medical</option>
</select>
</td>
</tr>
</table>
</div>
<script type="text/javascript">
$("#setCustomTagForDocument").change(function() {
tabDocumentSearch_setCustomTag()
});
</script>
<div class="prev-btn">
<img onclick="TabDocumentSearch_emailContentsViewNextPrev('prev')"
src="http://witnesstreefiles.s3.amazonaws.com/stable/liquis/images/prev.png"
width="25" />
</div>
<div class="next-btn">
<img onclick="TabDocumentSearch_emailContentsViewNextPrev('next')"
src="http://witnesstreefiles.s3.amazonaws.com/stable/liquis/images/next.png"
width="25" />
</div>
</div>
<div class="clear"></div>
</div>
<div class="clear"></div>
</div>
<script type="text/javascript">
$("#tabDocumentData_documentCustomComment").keydown(function(event) {
if (event.keyCode == 13) {
tabDocumentSearch_tabDocuments_updateComment()
}
})
</script>
I solved a similar jQuery problem that only affected IE. The <br> tags in callbackReturnData may be the culprits (plus any other unclosed tags/invalid HTML). Try closing them like: <br />.
Relevant jQuery( html, [ ownerDocument ] ) documentation:
To ensure cross-platform
compatibility, the snippet must be
well-formed. Tags that can contain
other elements should be paired with a
closing tag... Tags that cannot
contain elements may be quick-closed
or not.
(I know <br> cannot include other elements, but removing this tag fixed the problem. Also it doesn't seem to be an issue with jQuery 1.6/IE9, anymore.)
This is purely a guess but I think jQuery has issues adding html like that. does it work if you go straight javascript?
var d = document.createElement('div');
d.setAttribute('id', 'test');
d.innerHTML = callbackReturnData;
document.getElementById('parent_tabDocumentSearch_displayMessageContents').appendChild(d);
Alternatively, I think you can try something like
var $div = $("<div id='test'>" + callbackReturnData + "</div>");
$("#parent_tabDocumentSearch_displayMessageContents").append($div);
I had an extra closing tag in my appended html that was causing this issue for me. No error from IE, just a failure to add anything to the DOM.