I m adding a row in a table via jquery. Every row has some javascript associated with it.
When i add a new row using jquery, the javasccript works on previous rows, but not on newly added row.
Do i need to load the same js again ?? if yes, how?
js works on already html row, but not on row i added
<table>
<tr id="hello12">
<div class="formField" style="float:right" >
<span class="btn btn-success fileinput-button" >
<i class="glyphicon glyphicon-plus"></i>
<span>Add Attachments...</span>
<input id="fileupload" type="file" name="attachment" multiple>
</span>
</div>
</tr>
</tr>
<tr class="row">
<td>
<button type="button" id="override_button">
<b>+</b>
</button>
</td>
</tr>
</table>
$('#fileupload').fileupload({
url: '/attachments/create',
dataType: 'json',
done: function (e, data) {
alert("done");
},
});
$('#override_button').click(function(){
alert("hello")
$('#hello12').after('\ <tr id="hello12">
<div class="formField" style="float:right" >
<span class="btn btn-success fileinput-button" >
<i class="glyphicon glyphicon-plus"></i>
<span>Add Attachments...</span>
<input id="fileupload" type="file" name="attachment" multiple>
</span>
</div>
</tr>')
});
You can use on jquery function :
$("table").on("click", "#override_button", function(event){
alert("done");
});
or if you use jquery prior to 1.7 check live function
example: http://jsfiddle.net/rad_101/99q5jwrx/1/
Case 1: You are hard-bound to reload the script(which I donot feel is a necessity at all). You can save the script in an external file, and append it to the head of your html page.
<script language="text/javascript">
function load_js()
{
var head= document.getElementsByTagName('head')[0];
var script= document.createElement('script');
script.type= 'text/javascript';
script.src= 'source_file.js';
head.appendChild(script);
}
// call the function, so as to run the scripts again on the page
load_js();
</script>
Case 2: (More efficiently) Use (as Dimitris Nastos pointed out)
$(document).on("click", "table .row", function(){
//write your "ASSOCIATED JS" code here.
});
This binds a click event to the document and all child elements within it. It then matches the element identifier provided as the second argument. Works on dynamic elements too.
Case 3: (Little more efficiently) In your case, table is a static element, and would the parent element of the new row. Hence, instead of traversing the whole DOM while writing $(document).on("click","element",function(){}), use
$(table).on("click", "table .row", function(){
//write your "ASSOCIATED JS" code here.
});
So Finally after lot of struggle i got the answer,
Fileupload binds the action to the html once it is loaded, so if you add a new html to the page ,
for each element you have to bind the fileupload again.( you can also use live action to add events to button, in that case you do not need to bind again)
var dofileupload = function(){
$('#fileupload').fileupload({
url: '/attachments/create',
dataType: 'json',
done: function (e, data) {
alert("done");
},
});
}
$('#override_button').click(function(){
alert("hello")
$('#hello12').after('\ <tr id="hello12">
<div class="formField" style="float:right" >
<span class="btn btn-success fileinput-button" >
<i class="glyphicon glyphicon-plus"></i>
<span>Add Attachments...</span>
<input id="fileupload" type="file" name="attachment" multiple>
</span>
</div>
</tr>')
}).each(function () {
dofileupload
}
This solves my problem
Related
I have a table that is generated from server side on a partial and rendered using ajax. Because of this I lose binding.
So my only option is to map everything to a JavaScript array and post it.
Is there a way to map everything using jQuery without having to iterate every row then every column and look for each input one by one?
Are there any other options? Perhaps I have to use something like Vue?
Here is my partial:
#model Project.Areas.Robotics.Models.ViewModels.DefectRecordViewModel
<form method="post">
<card>
<card-header icon="fas fa-thumbs-down" title="Peças NOK">
</card-header>
<card-body>
<div class="form-row">
<div class="form-group col-md-6">
<h4>
<span class="">
<b><i class=""></i>Registo</b> #Model.ProductionRecordId
</span>
</h4>
</div>
</div>
<div class="form-row">
<div class="form-group col-md-6">
<label asp-for="References"></label>
<select id="references-nok" asp-items="Model.References" class="custom-select custom-select-sm" onchange="selectReferences(this)">
<option value="">--</option>
</select>
</div>
</div>
<div class="table-responsive">
<table id="tblDefects" class="table table-sm" style="width:100%;">
<thead class="bg-olive">
<tr>
<th>#Html.DisplayNameFor(model => model.DefectCodes[0].DefectCodeId)</th>
<th>#Html.DisplayNameFor(model => model.DefectCodes[0].Quantidade)</th>
<th>#Html.DisplayNameFor(model => model.DefectCodes[0].Detalhes)</th>
</tr>
</thead>
<tbody>
#for (int i = 0; i < Model.DefectCodes.Count(); i++)
{
<tr>
<td>
#Html.DisplayFor(model => model.DefectCodes[i].DefectCode)
<input type="hidden" asp-for="DefectCodes[i].DefectCodeId" />
<input type="hidden" class="reference-holder" asp-for="DefectCodes[i].ReferenceId" />
<input type="hidden" asp-for="DefectCodes[i].DefectCodeId" />
</td>
<td>
<input asp-for="DefectCodes[i].Quantidade" class="form-control form-control-sm" />
<span asp-validation-for="DefectCodes[i].Quantidade" class="text-danger"></span>
</td>
<td>
<input asp-for="DefectCodes[i].Detalhes" class="form-control form-control-sm" />
<span asp-validation-for="DefectCodes[i].Detalhes" class="text-danger"></span>
</td>
</tr>
}
</tbody>
</table>
</div>
</card-body>
<card-footer>
<div class="form-row">
<div class="form-group col-md-6">
<button type="button" data-url="#Url.Page("Index","AddDefectCode")" onclick="addDefectRecord(this)" class="btn btn-success btn-sm"><i class="fas fa-plus"></i> Adicionar</button>
<button type="button" onclick="hideDetails()" class="btn btn-danger btn-sm"><i class="fas fa-times"></i> Cancelar</button>
</div>
</div>
</card-footer>
</card>
</form>
I am unable to understand clearly what is Your problem but if You have large number of records and You don't want to load complete at once or want to reload your table without reload or all functionality like paging searching and filter you can use data table plugin
with server side record manipulation if this you are question you can reply this post so i can give you more example or i will give you some example .for your further understanding .
other wise you can elaborate your question with some screen shot so i can understand your roots of problem and give the best possible answers .
Is there a way to map everything using jQuery without having to iterate every row then every column and look for each input one by one?
Since you've configured all the <input/> with well-formed names, you can build a FormData directly.
var formdata = new FormData(someFormElement);
For example, add a submitDefectCode function to send an ajax request as below:
<script>
function submitDefectCode(element){ // the element is the `<button/>` that is clicked
var url = element.getAttribute("data-url");
var form = document.querySelector("form"); // get the `<form>` element
var formdata = new FormData(form);
$.ajax({
method:"post",
url: url,
contentType: false,
processData: false,
data: formdata,
success:function(resp){
console.log(resp); // now you get the response
}
});
}
</script>
And trigger this function when clicking the button:
<button type="button" data-url="#Url.Action("Index","AddDefectCode")"
onclick="event.preventDefault(); submitDefectCode(this);"
class="btn btn-success btn-sm">
<i class="fas fa-plus"></i> Adicionar
</button>
Finally, make your server side code to receive the form data with a [FromForm] attribute:
[HttpPost("/AddDefectCode")] // change this route as you need
public IActionResult TestPost([FromForm]DefectRecordViewModel model)
{
// ... now you get the model automatically
return Json(model);
}
Demo:
Here's a demo screenshot when posting data with multiple table rows:
In case you want to build a javascript array manually, you can use the FormData.entries():
var array= [];
for(var pair of formData.entries()) {
array.push({key: pair[0], value:pair[1]});
}
I used ajax unobtrusive to submit the form on the partial. The model is automatically binded on serverside, no need to do anything manually.
I am using Krajee's Bootstrap file upload plugin for file input & I am trying to clone the file input so that users can add multiple files from different folders rather than selecting it at once. The issue I am facing is after the file input gets cloned, it behaves weirdly. I have setup a fiddle for this.
When I am trying to reset or clear the file input, it always clears the first input. Have been trying a lot of options & after spending so many hours decided to post here.
JS Fiddle: https://jsfiddle.net/asfg9mna/
Any ideas as to how to make it work fine? Issue is whenever i click on delete icon, it always deletes the first input's file & not the current one.
HTML code:
<form role="form" id="upload-form" class="form-horizontal">
<div class="addFiles text-nowrap">
<div class="appendClass form-group" style="margin-bottom: 1.5%;">
<label class="col-md-2 control-label" for="input-2">Select Files</label>
<div class="col-md-9 col-9-input uploadFile">
<input placeholder="Select Files" id="input-2" name="input2[]" type="file" class="file input-upload" data-show-upload="false" data-show-preview="false">
</div>
<button type="button" class="btn btn-box-tool addFilesBtn" data-toggle="tooltip" title="Click to add more files">
<i class="fa fa-plus"> </i>
</button>
<button type="button" class="btn btn-box-tool closeFilesBtn" data-toggle="tooltip" title="Click to remove this block">
<i class="fa fa-times"> </i>
</button>
</div>
</div>
</form>
JS Code:
//Clone Upload File Div
$(document).on('click', ".addFilesBtn", function(e) {
e.preventDefault();
$(this).tooltip('hide');
$(".appendClass:first").clone(true).appendTo(".addFiles");
$('.closeFilesBtn').show();
$('.closeFilesBtn:first').hide();
//$fileInput = $('.input-upload');
//$fileInput.replaceWith( $fileInput = $fileInput.clone( true ) );
//$('.input-upload').fileinput('clear').fileinput();
$('.uploadFile').next().trigger('reset');
});
Here is jsfiddle
Update your js code like this,
$(document).on('click', ".addFilesBtn", function(e) {
e.preventDefault();
$(this).tooltip('hide');
parent_element = $(".appendClass:first");
$(".input-upload").fileinput('destroy');
element = parent_element.clone();
element.appendTo(".addFiles");
$(".input-upload").fileinput();
$('.closeFilesBtn').show();
$('.closeFilesBtn:first').hide();
//$fileInput = $('.input-upload');
//$fileInput.replaceWith( $fileInput = $fileInput.clone( true ) );
//$('.input-upload').fileinput('clear').fileinput();
//$('.uploadFile').next().trigger('reset');
});
And please write your code to update ids of every elements which will be cloned.
EDIT
$(document).on('click', ".addFilesBtn", function(e) {
e.preventDefault();
$(this).tooltip('hide');
$(".has_clone").each(function() {
$this = $(this);
var parent_element = $(this).closest(".appendClass");
var $element = parent_element.clone();
$element.find(".file-input").remove();
var counter = parseInt($("#counter").val()) + 1;
$element.find(".col-md-9").append('<input placeholder="Select Files" id="input-' + counter + '" name="input2[]" type="file" class="file dynamic_clone input-upload " data-show-upload="false" data-show-preview="false">');
$("#counter").val(counter);
$element.appendTo(".addFiles");
$(".input-upload").fileinput({
'showPreview': true
});
});
$('.closeFilesBtn').show();
$('.closeFilesBtn:first').hide();
});
//Close addFile div - Upload files
$(document).on('click', ".closeFilesBtn", function(e) {
e.preventDefault();
$(this).closest(".appendClass").hide();
});
Thanks
I used ajax script and a partial view to post and retrieve a data without any postback or view flickering. Using the ajax script below would return the partialview with its content in a specified div element called "ajaxcom" as you can see on the script below. Now, I noticed that after the data("which is the partialview") is retrieve and displayed on the specified div element of a view, it seems that it's like a static or it became like read-only file because it doesn't respond anymore, in which I meant that, on that partialview I have some functionalities like button to click with corresponding jquery codes but it's not even firing or responding when you click any button on it. Is this normal scenario that if you want to display a partial view in a specified div element using ajax script would behave like this? If so, what are my options here if I still want to resume the functionalities within that partial view like I want to click a button on it? Any thoughts or suggestions? Thanks...
Ajax Script:
$.ajax({
url: '/AjaxComms/AjaxComments',
type: "POST",
data: dataObject,
dataType: "json",
success: function(result) {
$.ajax({
url: '/AjaxComms/DisplayPartial',
type: "GET",
contentType: 'application/html; charset=utf-8',
data: dataObject,
dataType: "html",
success: function (result) {
$('#ajaxcom').html(result); // this is where I'm displaying my partial view
}
})
},
error: function (result) {
alert(status);
}
});
PartialView:
#model CRUD_AJAX.Models.CommentReplyModel
<script src="~/Scripts/jquery-1.7.1.min.js"></script>
<script src="~/Scripts/jquery.validate.min.js"></script>
<script src="~/Scripts/jquery.validate.unobtrusive.min.js"></script>
<table id="mytable">
#foreach (var item in Model.Comments )
{
<tr >
<td class="tdstyle" >
<div style="font-weight:bold;"> #Html.DisplayFor(modelItem => item.name) </div>
<p class="comment more" style ="white-space: pre-line; margin-top:0px;margin-bottom:0px; border-radius: 4px 4px 4px 4px; max-width :500px; min-height :5px; display :block; background-color: #CCCCFF"> #Html.DisplayFor(modelItem => item.comment) </p>
<p style="margin-top:2px;margin-bottom:0px"> <input type="button" id="like" name="like" value="Like" style="color:blue;border:0px;background-color:inherit;cursor:pointer" /> <input type="button" class ="Reply" name="Reply" value="Replie(s)" style="margin-bottom:0px;color:blue;border:0px;background-color:inherit;cursor:pointer" /></p>
<div id="divReply" class ="divrep" style=" position:relative;left:50px; overflow:auto;margin-top:0px;margin-bottom:0px">
<table>
#foreach (var item2 in Model.Replies.Where(r => r.Id == item.Id))
{
<tr >
<td >
<div style="font-weight:bold;"> #Html.DisplayFor(modelItem => item2.name) </div>
<p class="comment more" style ="margin-top:0px;margin-bottom:0px;white-space:pre-line; border-radius: 4px 4px 4px 4px; max-width :445px; min-height :5px; display :block; background-color: #CCCCFF;">#Html.DisplayFor(modelItem=>item2.reply) </p>
</td>
</tr>
}
</table>
<div class="editor-field" style="display:none; margin-bottom:5px;margin-top:5px">
<input type="text" id="comidvalue" name="idrep" value="#Html.DisplayFor(modelItem => item.Id)" />
<span class="field-validation-valid" data-valmsg-for="idrep" data-valmsg-replace="true"></span>
</div>
<br />
<input type="text" id="namerep" name="namerep" style="width:445px;resize:none" />
<span class="field-validation-valid" data-valmsg-for="namerep" data-valmsg-replace="true"></span>
<br />
<textarea id="reply" name="reply" style="width:445px;height:100px;resize:none" ></textarea>
<span class="field-validation-valid" data-valmsg-for="reply" data-valmsg-replace="true"></span>
<br />
<input type="button" class="postrep" value="Post Reply" name="butname" style="cursor:pointer" />
<br />
</div>
</td>
</tr>
}
</table>
When you attach a click handler to an element using
$('button.postrep').click(function() {...
it is applied to that element only. When your insert a new button element as you are doing with your AJAX call, the click event is not applied to the new element. In this case you need to use event delegation using jquery .on method. From the documentation "Delegated events have the advantage that they can process events from descendant elements that are added to the document at a later time.".
In your case the closest element which is not dynamically updated is the element with id="ajaxcom" so your script to handle the click event of any dynamically added button with class="postrep" would be
$('#ajaxcom').on('click', '.postrep', function() {
// do something
});
When the file input changes and receives a value, i want to set that value to a tr.file_name. After that i want to clone that TR and paste it to the
Cloning works, but for multiple files it is not working. Anyone that can help me?
<tr class="file_row">
<td class="file_title"></td>
<td class="text-center">
<a class='btn btn-info btn-xs' href="#">
<span class="glyphicon glyphicon-edit"></span> Edit
</a>
<a href="#" class="btn btn-danger btn-xs">
<span class="glyphicon glyphicon-remove"></span> Del
</a>
</td>
<td>
<div class="fileUpload btn btn-primary btn-xs">
<span><b>+</b> Upload</span>
<input type="file" class="upload" />
</div>
</td>
</tr>
Javascript:
$(document).ready(function(){
var filename
$('.file_row').change(function(){
file();
});
file();
function file(){
var empty = true;
var filename;
$('.file_row').each(function(){
filename = $(this).find('.upload').val();
$(this).find('.file_title').text(filename);
if(filename != ''){
empty = false;
}
});
if(empty == false){
var row = $('.file_row:first-child').clone();
$(row).find('.upload').val('');
$(row).appendTo('table');
}
}
});
I've also made a fiddle.
Change your event binding from this:
$('.file_row').change(function(){
file();
});
To this:
$('table').on('change','.file_row', function(){
file();
});
As the method change only bind to events that are already on the page when you invoke it. Delegating the event to a common parent works when the element is added dynamically.
You forget to clean the file_title in the cloned tr
$(row).find('.file_title').text('');
updated jsfiddle: http://jsfiddle.net/a23ez9eg/4/
I have a file upload button with auto upload enabled as follows:
<form id="fileupload" action="home/uploadprofilepic" method="POST" enctype="multipart/form-data">
<span class="btn btn-success fileinput-button">
<i class="icon-plus icon-white"></i>
<span>Add files...</span>
<input type="file" name="files">
</span>
</form>
$(document).ready(function()
{
$("input[name=files]").change(function() {
$(this).closest("form").submit();
});
});
However, I want to dynamically insert this as html. I need to add the autoupload javascript too. This is what I have so far :
$('#uploadPicId').popover({
title : 'Edit Profile Picture', //this is the top title bar of the popover. add some basic css
html: 'true', //needed to show html of course
content : '<form id="fileupload" action="home/uploadprofilepicmeta" method="POST" enctype="multipart/form-data">'+
'<span class="btn btn-success fileinput-button">'+
' <i class="icon-plus icon-white"></i>'+
' <span>Add files...</span>'+
' <input type="file" name="files">'+
'</span>'+
'</form>'
});
I need to add javascript to make the autoupload work. Is there any way to do this? I am pretty lost.
Thanks.
Change your above js to be like this instead:
$(document).ready(function()
{
$("body").on("change", "input[name=files]", function() {
$(this).closest("form").submit();
});
});
The key difference is your setting up the event listener on the entire body and if the event was launched from the given input, fire your function no matter if the html was added dynamically or not.