How To Handle Event On Dynamic Parent Child Object - javascript

I am still not statisfy regarding Dynamic Child Inside Dynamic Parent where a lot of confusing for me and more worst how to know which once and how I can manipulate them to what I want.
For yours informations I am very very new on Javascript and Jquery, but I can catch up if someone give a right directions and a rights syntax. I love clean code where from that code I can learn more and understand.
Let say I have this structure html where it's same on firebugs:-
<div name="div0" class="div0">
<input name="txt0" class="txt0">
<br/><br/>
<div name="div1[]" class="divL1">
<button class="btn1"></button>
<button class="btn2"></button>
<input name="txtL1_a[]" class="cLtxt1">
<input name="txtL1_b[]" class="cLtxt1">
<br/><br/>
<div name="div2[]" class="divL2">
<div id="ui-widget">
<input name="txtL2_a[]" class="cLtxt2 autosuggest">
</div>
<input name="txtL2_b[]" class="cLtxt2">
</div>
<br/><br/>
<div name="div1[]" class="divL1">
<button class="btn1"></button>
<button class="btn2"></button>
<input name="txtL1_a[]" class="cLtxt1">
<input name="txtL1_b[]" class="cLtxt1">
<br/><br/>
<div name="div2[]" class="divL2">
<div id="ui-widget">
<input name="txtL2_a[]" class="cLtxt2 autosuggest">
</div>
<input name="txtL2_b[]" class="cLtxt2">
</div>
</div>
<br/><br/>
Actually on my head have a lot of question but let me ask a few question first.
1. I want to run .autosuggest where it's complicated for me because on normal form before this I can manage run it, but when .autosuggest inside dynamic parent div and located on dynamic input I cannot get a value and show a autocomplete.
By given id "txtL2_a[]" function SearchText cannot performance autocomplete and don't know which index are doing that.
function SearchText() {
$(".autosuggest").autocomplete({
source: function (request, response) {
$.ajax({
type: "POST",
contentType: "application/json; charset=utf-8",
url: "frmsetuptrip.aspx/GetAutoCompleteData",
minLength: 3,
data: "{'presearch':'" + document.getElementById('txtL2_a[]').value + "'}",
dataType: "json",
success: function (data) {
if ((data.d).length == 0) {
//$('#button9').show();
var result = [
{
label: 'No matches found',
value: response.term
}
];
response(result);
}
else {
response(data.d);
}
},
error: function (result) {
alert("Error");
}
});
}
});
}
2. Let say on
<div name="div1[]" class="divL1"> //index 1
I need some auto fill up - let say when I fill up
<input name="txtL2_a[]" class="cLtxt2 autosuggest"> //index :1
automatically value inside
<input name="txtL2_b[]" class="cLtxt2"> 'Index 1
will change only based parents index.
3. There is anyway a one function where I can catch all event and elaborate that by IF before go specific sub function or task like this pseudo code below:-
$("div.div0").each(function (event) {
if (event=="keyup" on child=="divL1"+index[0]){
//detect more spesific which object are doing that
if (whoisdoing=="txtL1_a[]"+index[0] {
//then do action etc: fill up parent input
$("div0.txt0").val($(txtL1_a.index[0]).val());
}
if (whoisdoing=="txtL1_b[]"+index[0] {
//then do action etc: fill up childs input
$("div2[index[0]].txtL2_b[index[0]].val( $(txtL1_b[index[0]]).val() );
}
}
//event - keypress
//event - click
//and many more
});
I cannot find on internet regarding all this matter I mention above. If anybody have a solution or already develop that function please sharing and I believe this is not easy to handle.
Anyway thanks on advance to you for reading and replying my question.
Best Regards.

I think and think again - it's should be have an solution!
Rights now I can handle KEYUP and Click on my dynamic child which specific input tag where I can do some task. I found on dynamic child inside dynamic parent I need use direct Class Name and Catch Parent Index first.
You cannot use this syntax below for my html structure:-
$(document).ready(function () {
var buttons = document.getElementsByTagName('button');
var buttonsLength = buttons.length;
for (var i = 0; i < buttonsLength; i++) {
buttons[i].addEventListener('keyup', clickResponse, false);
};
});
function clickResponse() {
// do something based on button selection here...
}
I found above syntax only can run on first level Parent only without dynamic child/parent add on run time.
What I do is using this syntax below to solve my problem number 2 and 3.
$("div.div0").on("keyup", "input", function () {
//detect name and val which input are doing keyup
handler = $(this).val();
name = $(this).attr('name');
parHandler = name;
//only this input I want do some task
if (name == "txtL1_a[]") {
dcAction = "FillUpOtherInput";
FillUp; //run functions
}
});
function FillUp() {
if (dcAction == "FillUpOtherInput") {
alert("Handler Name: " + parHandler + " Index Level :" + dc2);
//make sure right Parent Index before insert a value
//--should i loop
$("div.purchase-items").each(function (i) {
alert(i);
if (i == dc2) {
$(this).find("input[name='txtL1_b[]']").val("Hai");
}
i+1
});
parHandler = "";
dc2 = "";
dcAction = "";
}
}
Yes! I can fill up value to other input on same Parent Index.
If anybody have problem regarding Dynamic Child inside Dynamic Parent on do action like me, yours can refer this syntax to solve your problem.
If anyone have better solutions please share here to help other person like me as newbie on Jquery functions.

For question No 1 regarding autocomplete where is detect which dynamic child are doing I use this line syntax:-
function SearchText(pIndex,iValue) {
//alert(dc2 + "/" + iValue);
$("div.divL2").eq(pIndex).find(".autosuggest").autocomplete({
source: function (request, response) {
$.ajax({
type: "POST",
contentType: "application/json; charset=utf-8",
url: "frmsetuptrip.aspx/GetAutoCompleteData",
minLength: 3,
data: "{'presearch':'" + $("div.divL2").eq(pIndex).find("input[name='txtL2_a[]']").val() + "'}",
dataType: "json",
success: function (data) {
if ((data.d).length == 0) {
//$('#button9').show();
var result = [
{
label: 'No matches found',
value: response.term
}
];
response(result);
}
else {
response(data.d);
}
},
error: function (result) {
alert("Error");
}
});
}
});
}
Now my autocomplete can catch txtL2_a[] value and know which parent are to show a list.
What I learn and like to share to yours is a key
$("div.divL2").eq(pIndex).find(".autosuggest")
$(-what is parent name-).eq(-put parent index-).find(-class name on input-)
then it's should be run!.
I am new and must thanks to all who read this question and hope someone can get some idea from what I wrote up here.
Who's are trying intentionally to help me like #baao I really appreciate it and many thanks.
Yours are welcome to share if any better syntax/script on this matter to put on, maybe it's can help a thousand out there are search and face a problem same like me.
And I am glad and honest to share my code what I already know and solving a matter regarding my situations.

To make shorter syntax on fillup function follow this below:-
function FillUp() {
if (dcAction == "FillUpOtherInput") {
$(div.div0).eq(dc2).find("input[name='txtL1_b[]']").val("Hai");
parHandler = "";
dc2 = "";
dcAction = "";
}
}
I just know eq(***if you know the index*)** are direct go to specific element like dynamic parent/child based index given.

Related

Jquery keyup event firing more than once

I'm trying to display some content from my database in a div, every time a user types a value into an input box. I'm using jquery to do this. But whenever I type something, once into the input box... the call-back function repeats, four times.
getProducts(){
$('.search-products').on('keyup', function(){
const searchProducts = new SearchProducts();
let search = $.trim($(this).val()); // get search text
if(search!==""){
// let data = {search: search};
let url = '/search-for-products/' + search;
$.ajax({
type: "GET",
url: url,
data: {},
success: function(response){
if(response.success){
searchProducts.showSearchProducts(response.products);
}
}
});
}
});
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input type="text" class="form-control search-products" placeholder="What are you searching for ?" aria-label="Username" aria-describedby="basic-addon1" style="color: light grey;">
I'd like your honest opinions on what could be wrong, with my code. Cos, I'm now confused about what to do.
If you've not found why it's added twice, a simple fix is you can remove the listener before adding it again:
$('.search-products').off('keyup').on('keyup', ...)
You can also use namespace events, to not remove other keyup events:
$('.search-products').off('keyup.search').on('keyup.search', ...)
Not many people know that jQuery supports namespace events.

How to populate input fields dynamically created based on another one after an AJAX request is done?

I have this HTML code that dynamically adds barcode[] and description[] input fields to my form, using the onfocusout event, the get_barcode_data JS function below is triggered to get the barcode description, but it only works for a single barcode[] input field:
<div>
<input type="text" id="barcode[]" name="barcode[]" onfocusout="get_barcode_data(this);"/>
</div>
<div>
<textarea id="description[]" name="description[]" disabled="disabled"></textarea>
</div>
<div align="center">
</div>
The console.log(name) call displays the value I entered on any of the dynamically created barcode[] input fields and the request is successfully done but after that I don't know how to point the response to the right barcode[] and description[] fields:
function get_barcode_data(element)
{
var name = element.value;
console.log(name);
$.ajax({
method: 'POST',
url: 'include/get_barcode_data.php',
data: {
barcode: name
},
success: function(response){
if (response == 'FALSE') {
$('#barcode[]').focus();
$('#barcode[]').val('');
$('#description[]').val('');
var message = 'Invalid barcode.';
alert( message );
} else {
var res = jQuery.parseJSON(response);
$('#description').val(res.description);
}
}
});
}
Any ideas on how to solve this would be much appreciated.
Like James pointed out in the comment section, you cant have duplicate IDs in your document. You should either generate unique IDs for each element, or remove the IDs altogether.
If you generate unique IDs, you can pass the generated ID to your event handler and use it to select the correct element.
<div>
<input type="text" id="barcode_123" name="barcode[]" onfocusout="get_barcode_data(this, 'description_123');"/>
</div>
<div>
<textarea id="description_123" name="description[]" disabled="disabled"></textarea>
</div>
<div align="center">
</div>
123 should be a dynamically generated number.
And in your handler:
function get_barcode_data(element, target_id)
{
var name = element.value;
console.log(name);
$.ajax({
method: 'POST',
url: 'include/get_barcode_data.php',
data: {
barcode: name
},
success: function(response){
if (response == 'FALSE') {
$(element).focus();
$(element).val('');
$('#' + target_id).val('');
var message = 'Invalid barcode.';
alert( message );
} else {
var res = jQuery.parseJSON(response);
$('#' + target_id).val(res.description);
}
}
});
}
I would like to point out though, that this is not very good practice. Code like this get hard to maintain and breaks easily.
You would really be better off by learning a well though out framework, like Vue.js, Angular or React.

jquery ajax request wrapped in jQuery()'s .text() isn't the same as the div's .text()?

I know this is a very concrete issue but I've struggled with this code for the last 2 hours and I can't find anything on the topic or figure out how to solve it.
I have an issue with a jQuery Ajax Post request. I am trying to make a section on my page where I display the users current level. When a user interacts and does something that increases the level on the site the level should also increase in the DOM/client's browser. Therefore I've added a setinterval that allows the request to run every 5th second. And if the $(response).text() is different from the current div's .text() where i am rendering the current level I want to append this new response from the ajax request.
Maybe the answer is more obvious than I think.... I have added the code below
Ajax page:
$(document).ready(function () {
function getLevel() {
var getLvlData = $.ajax({
url: "AjaxRequests.php",
type: "POST",
data: {type: "4", lvl_r_type: 1}
});
getLvlData.done(function (response, textStatus, jqXHR) {
var innerLevelHTML = $("#LevelContainer");
if (($(response).text()) != ($(innerLevelHTML).text())) {
innerLevelHTML.html("");
innerLevelHTML.append(response);
}
if ($(response).text() == $(innerLevelHTML).text()) {
alert("the same");
}
});
}
var levelChecker = setInterval(function () {
getLevel();
}, 1000);
getLevel();
});
AjaxRequests.php:
if ($_POST["type"] == "4" && isset($_POST["lvl_r_type"])) {
$returnVal = htmlentities($_POST["lvl_r_type"]);
if (!empty($returnVal)) {
if ($returnVal == 1) {
?>
<div id="chartWrapper">
<div>
<canvas id="doughnut-chart"></canvas>
</div>
<div id="chart-center">
<div>
<div><h1>0%</h1></div>
<div><p>GX 0 / 1</p></div>
</div>
<div><p>LVL 0</p></div>
</div>
</div>
<div id="progressList">
<div><p>View tasks</p></div>
</div>
<?php
}
}
}
?>
html page
<div id="LevelContainer"></div>
Try using trim since a white space could be treated as a part of the text.
if (($(response).text().trim()) != ($(innerLevelHTML).text().trim())) {
...
One alternative approach I can think of, off of my head is, to set a hash inside a data attribute say data-hash="" whenever you set the html of that div, and then whenever you have a new ajax response you can generate a hash on the fly and compare that to the existing one and if a change is found just update the html and the hash value for that attribute.
This process minimises the confusion that may be caused due to dom being updated by some script.
Also, Instead of
innerLevelHTML.html("");
innerLevelHTML.append(response);
Why not just just set the html directly as
innerLevelHTML.html(response);

Properly use bootstrap switch which call c# function (T4MVC/Entity Framework)

I can't find words to explain without code, so here's what I got so far:
View: (bootstrap switch)
[...]
#foreach (var item in Model)
{
<tr>
<td>
<input class="my-checkbox" type="checkbox" name="my-checkbox" id="#(item.Id)" data-handle-width="100" data-on-text="Activer" data-off-text="Désactiver" data-size="small" data-on-color="success">
</td>
</tr>
}
[...]
<script type="text/javascript">
var isEnableUrl = '#Url.Action("IsEnabledMaterial", "MaterialType")';
$("[name='my-checkbox']").bootstrapSwitch();
</script>
Javascript:
$(document).ready(function () {
$('.my-checkbox').each(function (index) {
$.ajax({
type: 'POST',
url: isEnableUrl,
data: { 'id': index },
success: function (result) {
$('.my-checkbox').prop('checked', result);
},
error: function (e) {
swal("Error", "Can't modify that element. ", "error");
}
});
});
});
Then my controller:
[HttpPost]
public virtual bool IsEnabledMaterial(int id)
{
var materialType = materialTypeRepository.GetById(id);
return materialType.Enable;
}
So basically, what I'm trying to do, is on the load of the page, when all my "switch" are created, I want to go look in my database, to see which switch must be true or false and set them to the right value...
But when I'm trying to do that I get a NullReferenceException when the id = 0. Which is normal, I guess, 'cause in my database, the id's are 1, 2, 3 and 4. But if I increment by one the id, I get the same error when the id = 4. In every case, none of them get switch to true (they are all true in the DB). It will only work (for ids 1-2-3) if I do it manually (without .each), id: 0-4 are still failing to do what I want.
May it be with the foreach? 'Cause I tried passing the id "#(item.Id + 1)" and still got a 0 once...
Thanks very much for help!
I see at least three problems:
Your id to the input start with a number. Technically, the id should not start with a number. Try to change it to
<input class="my-checkbox" type="checkbox" name="my-checkbox" id="#("chkBox" + item.Id)" data-handle-width="100" data-on-text="Activer" data-off-text="Désactiver" data-size="small" data-on-color="success">
Your main issue should be
$('.my-checkbox').prop('checked', result);
This will change all the input with class="my-checkbox" to the last result from the ajax call. You might want to change it to
$('#chkBox' + index).prop('checked', result);
You will have performance issues as there are way too many ajax calls in this implementation

How to check if a ResultSet of an AJAX call using JQuery has value

I am Using iQuery to make AJAX Calls to the server and return a set of values. The Values returned are dynamic. The Result count being dynamic I am not able to look the result set and assign values to HTML Elements to show in Web Page.
Kindly advice how I could look if there is a value in the result set and use the same in my system. The Maximum count in result set is 16 and i have manually assigned values in the Script.
Calling the AJAX Method in the document ready of my Web Page.
$(document).ready(function () {
CallAJAX('../Forms/Send.aspx/refreshDash', '', 'FillMethod', 'FillMethodE');
});
AJAX Call Definition
function CallAJAX(ServerMethod, Parameters, SuccessMethod, ErrorMethod) {
$.ajax({
type: "POST",
url: ServerMethod,
data: Parameters,
contentType: "application/json; charset=utf-8",
dataType: "json",
error: function (xhr, status, errorThrown) {
Error = xhr; Result.d.ResultSet[0].TRCOUNT
eval(ErrorMethod + "()");
},
success: function (msg) {
Result = msg;
var rr = SuccessMethod + "();";
eval(rr);
}
});
}
Using Two jQuery Functions to Show Details and prompt Message when error is Raised. Note Error Function is not Shown.
function FillMethod() {
if ($.isEmptyObject(Result.d.ResultSet)) {
}
else {
$('[id$=lblCode1]').html(Result.d.ResultSet[0].DASH_NAME);
$('[id$=lblNot1]').html(Result.d.ResultSet[0].TRCOUNT);
$('[id$=lblCode2]').html(Result.d.ResultSet[1].DASH_NAME);
$('[id$=lblNot2]').html(Result.d.ResultSet[1].TRCOUNT);
$('[id$=lblCode3]').html(Result.d.ResultSet[2].DASH_NAME);
$('[id$=lblNot3]').html(Result.d.ResultSet[2].TRCOUNT);
$('[id$=lblCode4]').html(Result.d.ResultSet[3].DASH_NAME);
$('[id$=lblNot4]').html(Result.d.ResultSet[3].TRCOUNT);
$('[id$=lblCode5]').html(Result.d.ResultSet[4].DASH_NAME);
$('[id$=lblNot5]').html(Result.d.ResultSet[4].TRCOUNT);
$('[id$=lblCode6]').html(Result.d.ResultSet[5].DASH_NAME);
$('[id$=lblNot6]').html(Result.d.ResultSet[5].TRCOUNT);
$('[id$=lblCode7]').html(Result.d.ResultSet[6].DASH_NAME);
$('[id$=lblNot7]').html(Result.d.ResultSet[6].TRCOUNT);
$('[id$=lblCode8]').html(Result.d.ResultSet[7].DASH_NAME);
$('[id$=lblNot8]').html(Result.d.ResultSet[7].TRCOUNT);
$('[id$=lblCode9]').html(Result.d.ResultSet[8].DASH_NAME);
$('[id$=lblNot9]').html(Result.d.ResultSet[8].TRCOUNT);
$('[id$=lblCode10]').html(Result.d.ResultSet[9].DASH_NAME);
$('[id$=lblNot10]').html(Result.d.ResultSet[9].TRCOUNT);
$('[id$=lblCode11]').html(Result.d.ResultSet[10].DASH_NAME);
$('[id$=lblNot11]').html(Result.d.ResultSet[10].TRCOUNT);
$('[id$=lblCode12]').html(Result.d.ResultSet[11].DASH_NAME);
$('[id$=lblNot12]').html(Result.d.ResultSet[11].TRCOUNT);
$('[id$=lblCode13]').html(Result.d.ResultSet[12].DASH_NAME);
$('[id$=lblNot13]').html(Result.d.ResultSet[12].TRCOUNT);
$('[id$=lblCode14]').html(Result.d.ResultSet[13].DASH_NAME);
$('[id$=lblNot14]').html(Result.d.ResultSet[13].TRCOUNT);
$('[id$=lblCode15]').html(Result.d.ResultSet[14].DASH_NAME);
$('[id$=lblNot15]').html(Result.d.ResultSet[14].TRCOUNT);
$('[id$=lblCode16]').html(Result.d.ResultSet[15].DASH_NAME);
$('[id$=lblNot16]').html(Result.d.ResultSet[15].TRCOUNT);
}
};
function FillMethodE() {
}
Issue is being raised in the FillMethod function when only Result.d.ResultSet[0].DASH_NAME has a valid value and the following indexes does not have any values.
NOTE: Results are returned in pairs, if DASH_NAME is available then TRCOUNT will also be available for the same index.
All I need to do is irrespective of the result count i need to display in the labels in order values from the result set dynamically. Here are are two sets of result sets which could be obtained.
I'm afraid it's still really, really unclear what the specific problem is (and the sample result sets you posted don't provide any clarity on why you can't simply loop over them), but I'm willing to take a guess...
Is the problem that you're trying to write a dynamic set of results to a static set of placeholders for the output?
If that's the case, don't make the placeholders static. Just keep an empty space where you want the results to show and when you have the results, write them to that part of the page. You don't need HTML elements in place already, you can create them dynamically. For example:
success: function (msg) {
// let's assume msg is an array of data
for(var i = 0; i < msg.lengh; i++) {
$('#output').append(
'<div>' + msg[i].DASH_NAME + ' - ' + msg[i].DASHSTATUS + '</div>'
);
}
}
So if your #output is just a div, the result would look like this:
<div id="output">
<div>SEND CONFIRMED - 1</div>
<div>RECV HO RESPONDED - 4</div>
<div>RECV HO PAID - 3</div>
<!-- etc... -->
</div>
How you define and style that markup is entirely up to you, of course. The point is that you can create the markup on the fly from your JavaScript code, so it can be created dynamically based on the results from the AJAX request.
Try this
if (Result.d.ResultSet.length > 0) {
for (i = 0; i < Result.d.ResultSet.length; i++) {
$('[id$=lblCode'+i+']').html(Result.d.ResultSet[i].DASH_NAME);
$('[id$=lblNot1'+i+']').html(Result.d.ResultSet[i].TRCOUNT);
}

Categories

Resources