Stop duplicate values when appending from array to table in real time - javascript

I am currently running through a loop to pull values our of an array, and most of it works, but when I add a 2nd value it duplicates the new value and previous value into the table.
So when I add a row with value 488 it works fine:
<tr class="exe">
<td class="sipname">1446033619.75</td>
<td class="siptd">SIP/488-00000027</td>
<td><button class="btn btn-default unmute" id="mute" type="submit">Unmute</button></td>
<td><button class="btn btn-default kick" id="kick" type="submit">Kick</button></td>
</tr>
When I add another value then say 487 then duplicates the same row 488, 488, 487 in that order as so:
<tbody id="sip">
<tr class="exe">
<td class="sipname">1446033619.75</td>
<td class="siptd">SIP/488-00000027</td>
<td><button class="btn btn-default unmute" id="mute" type="submit">Unmute</button></td>
<td><button class="btn btn-default kick" id="kick" type="submit">Kick</button></td>
</tr>
<tr class="exe">
<td class="sipname">1446033619.75</td>
<td class="siptd">SIP/488-00000027</td>
<td><button class="btn btn-default mute" id="mute" type="submit">Mute</button></td>
<td><button class="btn btn-default kick" id="kick" type="submit">Kick</button></td>
</tr>
<tr class="exe">
<td class="sipname">1446033747.78</td>
<td class="siptd">SIP/487-00000028</td>
<td><button class="btn btn-default mute" id="mute" type="submit">Mute</button></td>
<td><button class="btn btn-default kick" id="kick" type="submit">Kick</button></td>
</tr>
</tbody>
All I need is 488,487 in table rows without duplicates, when i refresh the page it works fine. I am using socket.io (Express), node.js and Jquery.
I did find a small workaround using jquery remove, but it affects functionality I have meaning a minor bug so I need to not use the jquery remove.
socket.on('sipname', function (data, datad) {
var sipname = '';
var sipid = '';
$('.exe').remove();
for (var i = 0; i < data.length; i++) {
sipname = data[i];
sipid = datad[i];
if (sipname) {
$sip.append('<tr class="exe">\
<td class="sipname">' + sipid + '</td>\
<td class="siptd">' + sipname + '</td>\
<td><button class="btn btn-default mute" id="mute" type="submit">Mute</button></td>\
<td><button class="btn btn-default kick" id="kick" type="submit">Kick</button></td>\
</tr>');
}
}
});
Any ideas or guidance would be appreciated, this is stopping me from completing my first version of my application.

1st : again and again ID must be unique
2nd: you can try this code .. I changed Ids to Class so be sure to change it in your css stylesheet .. and use data-sipname in siptd class
socket.on('sipname', function (data, datad) {
var sipname = '';
var sipid = '';
$('.exe').remove();
for (var i = 0; i < data.length; i++) {
sipname = data[i];
sipid = datad[i];
if (sipname) {
if($('#sip > tr > .siptd[data-sipname = "'+sipname+'"]').length < 1){
$sip.append('<tr class="exe">\
<td class="sipname">' + sipid + '</td>\
<td class="siptd" data-sipname="'+ sipname +'">' + sipname + '</td>\
<td><button class="btn btn-default mute" type="submit">Mute</button></td>\
<td><button class="btn btn-default kick" type="submit">Kick</button></td>\
</tr>');
}
}
}
});
hope it help

It looks like $sip is a "global"-ish value outside the socket.on function. It gets filled with values on the first .on() call, and then adds any values again on the second .on() call.
The way to fix could be one of:
Only send new data to any .on() function. That way when you append, you don't have any duplicates.
If data into the .on() function is complete each time, you can just empty the $sip array each call. $sip = [] and then append everything fresh each time.
The more complicated option is a check on each element of the array to see if it exists yet. If not, add it, otherwise skip it. Using a hash could make that easier as well, storing the ID as the key and that HTML string as the value. Then checking for existence is quick, !!$sip[ sipname ] (does the property sipname in the object $sip evaluate to true).

Related

Having trouble sorting table with JQuery sort method

I am using PHP and JQuery to build a data table, I am using jQuery's .sort() method to sort the table. However, it is not working as excepted.
For the text fields, nothing is changed (except that the rows are rendered again).
For the numeric fields, the table sorts in a really weird manner.
Clearly the ID does not make sense like this? Here is my JavaScript code:
const rows = tbody.find('tr').sort((a, b) => {
let first, second;
if ($(e.target).attr('data-order') === 'asc') {
second = a;
first = b;
$(e.target).attr('data-order', 'desc');
}
else {
second = b;
first = a;
$(e.target).attr('data-order', 'asc');
}
const firstTd = $(first).children().eq($(e.target).attr('data-index') - 1).text();
const secondTd = $(second).children().eq($(e.target).attr('data-index') - 1).text();
// Take care of numbers
try {
return firstTd - secondTd;
}
catch (e) {
// Value is string
const value = firstTd.localeCompare(secondTd, "en");
return value;
}
}).appendTo(tbody);
Here is the source code for my table (I just added two rows):
<table class="table">
<thead>
<tr>
<th>
<button class="btn btn-light data-table-sort"
data-index="1" data-order="asc">
id <span class="fa fa-sort" aria-hidden="true"></span>
</button>
</th>
<button class="btn btn-light data-table-sort"
data-index="3" data-order="asc">
Text <span class="fa fa-sort" aria-hidden="true"></span>
</button>
</th>
<th></th>
</tr>
</thead>
<tbody>
<tr>
<td>72</td>
<td>af7c16d8f1</td>
<td>2021-11-26 06:16:55</td>
<td>
<form method="POST">
<input type="hidden" name="id" value="72">
<input type="submit" name="action" value="Details"
class="btn btn-info">
<input class="btn btn-primary" name="action"
type="submit" value="Edit">
<input data-id="72"
class="btn btn-danger data-table-delete"
name="action" value="Delete" type="submit">
</form>
</td>
</tr>
<tr>
<td>7</td>
<td>bedd6af3ed</td>
<!-- The same form as previous row -->
</td>
</tr>
</tbody>
</table>
I have made sure that tbody contains the correct value. I am also selecting the correct column. The table has to be dynamic and reusable so I can't hardcode everything.
Note: I have already tried appending rows to the table instead of the <tbody> element.
You probably need to detach elements since you reattach it again later:
tbody.find('tr').detach().sort...
This may need readjustments depending on how jQuery arrays are returned but detaching elements is the main idea and other things should be pretty trivial.

How to fix table row no being clicked after append function?

I am trying to create a new table row every time the associated button is clicked. However, once I click the button and I go to select the row, it does not get highlighted. I have an append function that passes a <tr> to the html. My end goal is to have the the new row that was appended become clickable and can be selected.
Code:
<div class="col-md-3 left-pane">
<div class="row justify-content-md-center">
<button class="btn btn-sm btn-block eNew">New Tier</button>
</div>
<hr>
<table class="table table-sm table-hover tAdd">
<tbody>
<tr>
<td>IIS</td>
<td><button class="btn btn-sm btnD">Delete</button></td>
</tr>
<tr>
<td>SQL</td>
<td><button class="btn btn-sm btnD">Delete</button></td>
</tr>
<tr>
<td>Windows File Share</td>
<td><button class="btn btn-sm btnD">Delete</button></td>
</tr>
<tr>
<td>Etc</td>
<td><button class="btn btn-sm btnD">Delete</button></td>
</tr>
</tbody>
</table>
</div>
Javascript:
$(".eNew").on("click", function(event){
$(".tAdd tbody").append(
"<tr>" +
"<td>New Selector</td>" +
"<td><button class=\"btn btn-sm btnD\">Delete</button></td>" +
"</tr>"
);
$(".tAdd tr").click(function() {
$(".tAdd tr").removeAttr('class');
$(this).toggleClass("table-active");
});
Also, it works for the original <tr> that is in the html file but for some reason when I append a table row it does not work.
This is entirely due to the fact that dynamic content is not bound using the event handler you have declared:
$(".eNew").on("click", function(event){
Although this will bind to all .eNew elements when the code first runs, new elements will not be bound.
Instead, bind to the document and specify .eNew as a selector for the click event and it will work:
$(document).on("click", ".eNew", function(event){
Edit following OP comment about not working
Just to verify that your code should now look like this:
$(document).on("click", ".eNew", function(event){
$(".tAdd tbody").append(
"<tr>" +
"<td>New Selector</td>" +
"<td><button class=\"btn btn-sm btnD\">Delete</button></td>" +
"</tr>"
);
});
$(document).on("click", ".tAdd tr", function(event){
$(".tAdd tr").removeAttr('class');
$(this).toggleClass("table-active");
});

How to delete a table line in angular js?

I`ve got a problem to delete items from object.
I made a function for deleting,but unfortunetly it can only delete 1 number in object.Like if i have 2 tasks and i choose to delete 2nd it will delete 1st one.
No idea how to fix it:(
$scope.deleteTask = function(taskIndex){
$scope.tasks.splice(taskIndex,1);
}
Here`s another code blocks for easier understanding of my code:
<tr ng-repeat="task in tasks">
<td>
<button class="btn btn-danger" ng-click="deleteTask(task)">Delete</button>
</td>
<td>{{task.taskName}}</td>
<td><input type="checkbox" ng-model="statusCheck"> </td>
<td style="{{setStyleToTd(statusCheck)}}">{{statusChecker(statusCheck)}}</td>
<td><button class="btn btn-primary">Edit</button></td>
</tr>
var taskInformation = [
{
taskName: "Test task"
, status: false
}
];
(I know there are lots of problems like mine but I didnt find a proper answer)
You should pass the id of the task not the task itself, try:
ng-click="deleteTask($index)"
It's better send object instead of index for delete. It should be like this
<button class="btn btn-danger" ng-click="deleteTask(task)">Delete</button>
$scope.deleteTask = function(task){
var taskIndex = $scope.tasks.indexOf(task);
$scope.tasks.splice(taskIndex,1);
}

Editable multiple forms on a table

I am using editable plugin to preform in place edit
This is the code I am using that I got from their Doc page, it is supposed to be used for adding new records, But I want to use it to modify records)
<script>
$(document).ready(function() {
//init editables
$('.myeditable').editable({
url: '/post',
placement: 'right'
});
//make username required
$('#new_username').editable();
//automatically show next editable
$('.myeditable').on('save.newuser', function(){
var that = this;
setTimeout(function() {
$(that).closest('td').next().find('.myeditable').editable('show');
}, 500);
});
//create new user
$('#save-btn').click(function() {
$('.myeditable').editable('submit', {
url: '/newuser',
ajaxOptions: {
dataType: 'json' //assuming json response
},
success: function(data, config) {
if(data && data.id) { //record created, response like {"id": 2}
//set pk
$(this).editable('option', 'pk', data.id);
//remove unsaved class
$(this).removeClass('editable-unsaved');
//show messages
var msg = 'New user created! Now editables submit individually.';
$('#msg').addClass('alert-success').removeClass('alert-error').html(msg).show();
$('#save-btn').hide();
$(this).off('save.newuser');
} else if(data && data.errors){
//server-side validation error, response like {"errors": {"username": "username already exist"} }
config.error.call(this, data.errors);
}
},
error: function(errors) {
var msg = '';
if(errors && errors.responseText) { //ajax error, errors = xhr object
msg = errors.responseText;
} else { //validation error (client-side or server-side)
$.each(errors, function(k, v) { msg += k+": "+v+"<br>"; });
}
$('#msg').removeClass('alert-success').addClass('alert-error').html(msg).show();
}
});
});
//reset
$('#reset-btn').click(function() {
$('.myeditable').editable('setValue', null)
.editable('option', 'pk', null)
.removeClass('editable-unsaved');
$('#save-btn').show();
$('#msg').hide();
});
});
</script>
And this is the html
<tr>
<td>adel</td>
<td></td>
<td></td>
<td></td>
<td><img src=""></img></td>
<td width="10%"><button id="save-btn" class="btn btn-primary btn-sm">Ok</button><button id="reset-btn" class="btn btn-sm pull-right">Reset</button></td>
</tr>
<tr>
<td>sdqsd</td>
<td></td>
<td></td>
<td></td>
<td><img src=""></img></td>
<td width="10%"><button id="save-btn" class="btn btn-primary btn-sm">Ok</button><button id="reset-btn" class="btn btn-sm pull-right">Reset</button></td>
</tr>
<tr>
<td>dzadz</td>
<td>from me with love</td>
<td>anywhere</td>
<td>http://justawebsite.com</td>
<td><img src=""></img></td>
<td width="10%"><button id="save-btn" class="btn btn-primary btn-sm">Ok</button><button id="reset-btn" class="btn btn-sm pull-right">Reset</button></td>
</tr>
Now everything works fine, Except if I edit one of the 2 first rows and hit Ok It will send the details of the last form http://justawebsite.com and sometimes it doesn't send anything, It is really messed up and I spent hours reading te documentation but I couldn't figure out the problem
As I said in my comment, you've got different elements with the same id, so the selectors won't work (id must be unique). Put them as class instead:
<tr>
<td>
adel
</td>
<td>
</td>
<td>
</td>
<td>
</td>
<td>
<a href="#" class="myeditable picture" data-type="text" data-name="picture" data-original-title="Enter Picture">
<img src="" />
</a>
</td>
<td width="10%">
<button class="btn btn-primary btn-sm save-btn">Ok</button>
<button class="btn btn-sm pull-right reset-btn">Reset</button>
</td>
</tr>
Here's a fiddle to get you started https://jsfiddle.net/virginieLGB/k2of9xor/1/
On there, you'll see that I've selected the editable elements you want to submit.
$('.save-btn').click(function() {
var that = $(this);
var allEditables = that.parents("tr").find(".myeditable"); // all ".myeditable" elements in the same "tr" as the ".save-btn" that was clicked on
allEditables.each(function() {
// here I've kept your code because I don't know what happens in your file, but maybe you need a bulk action
$(this).editable('submit', {
...
I don't know how your PHP file works, so don't know how you save your user and if you need to submit all fields at once or not. If so, you'll have to modify my answer a bit.
Have you tried refreshing it afterwards?
For me i noticed, that as soon as it was refreshed i got the result that i have been expecting, but only for one of them. However, i couldn't solve the problem yet.
Please let me know what kind of result you get.
Otherwise try debugging...disable one of the first rows and try it again..

Getting Error: [ngRepeat:dupes] in ng-repeat using angular.js

I am getting the following error while i have no data using ng-repeat in Angular.js
Error:
Error: [ngRepeat:dupes] http://errors.angularjs.org/1.4.6/ngRepeat/dupes?p0=user%20in%20objHodUserData&p1=string%3Al&p2=l
at Error (native)
at http://oditek.in/Gofasto/js/angularjs.js:6:416
at http://oditek.in/Gofasto/js/angularjs.js:279:39
at Object.fn (http://oditek.in/Gofasto/js/angularjs.js:129:128)
at n.$digest (http://oditek.in/Gofasto/js/angularjs.js:130:206)
at n.$apply (http://oditek.in/Gofasto/js/angularjs.js:133:236)
at g (http://oditek.in/Gofasto/js/angularjs.js:87:376)
at K (http://oditek.in/Gofasto/js/angularjs.js:91:448)
at XMLHttpRequest.z.onload (http://oditek.in/Gofasto/js/angularjs.js:92:462)
I am explaining my code below.
<tbody id="detailsstockid">
<tr ng-repeat="user in objHodUserData ">
<td>{{$index+1}}</td>
<td>{{user.user_name}}</td>
<td>{{user.email}}</td>
<td>{{user.mob_no}}</td>
<td>{{user.login_name}}</td>
<td ng-if="user.user_status==1">Enable</td>
<td ng-if="user.user_status==0">Disable</td>
<td>
<a ui-sref='hod.user'>
<input type='button' class='btn btn-xs btn-green' value='Edit' ng-click="editUserData(user.user_id)" >
</a>
</td>
<td>
<a ui-sref='hod.user'>
<input type='button' class='btn btn-xs btn-red' value='Delete' ng-click="deleteUserData(user.user_id);" >
</a>
</td>
</tr>
</tbody>
When the object objHodUserData has no data these type error is coming.I tried to resolve this by using track by $index. By using this error has gone but 4 blank rows are generating.Here i need when there is no data present no rows will generate without any error and when data will be there it will display.Please help me to resolve this error.
I had the same problem, and I solved it by wrapping all the <tbody> within a <div> element.
and inserting ng-show in this div element like that
<div ng-show="hasElements()">
and in your controller you have a $scope function to check if there is elements in the object like that:
$scope.hasElements = function(){
return objHodUserData.length ===0;
}
and that should work.
let me if it solved your problem.
Cheers.
Try using ng-if along with ng-repeat.It should be ng-if="objHodUserData.length !=0"
If you don't mind using lodash, then this is a handy utility library for your javascript, which can help with tasks like this.
var objHodUserDataWithoutBlanks = _.filter(objHodUserData, function(n) {
return n.user_name != "";
});
The above will filter out entries that have a blank username. Then your ng-repeat can instead repeat over this object without blanks: objHodUserDataWithoutBlanks.
Edit: Alternate method using only angularjs:
Add an angular filter:
myApp.filter('nonBlankOnly', function() {
return function( items) {
var filtered = [];
angular.forEach(items, function(item) {
if(item.user_name != "") {
filtered.push(item);
}
});
return filtered;
};
});
Then apply the filter in your controller:
function myCtrl($scope, $filter)
{
$scope.objHodUserDataWithoutBlanks = $filter('nonBlankOnly')(objHodUserData);
}
And repeat through filtered items:
<tr ng-repeat="user in objHodUserDataWithoutBlanks">
Maybe you can use de ng-show to check if there is an existing user, something like:
<tr ng-repeat="user in objHodUserData ">
<td ng-show="user">{{$index+1}}</td>
<td ng-show="user">{{user.user_name}}</td>
<td ng-show="user">{{user.email}}</td>
<td ng-show="user">{{user.mob_no}}</td>
<td ng-show="user">{{user.login_name}}</td>
or if you prefer to hide the entire row, put the ng-show on the <tr> element.
<tbody id="detailsstockid">
<tr ng-repeat="user in objHodUserData " ng-show="user">
<td>{{$index+1}}</td>
<td>{{user.user_name}}</td>
<td>{{user.email}}</td>
<td>{{user.mob_no}}</td>
<td>{{user.login_name}}</td>
<td ng-if="user.user_status==1">Enable</td>
<td ng-if="user.user_status==0">Disable</td>
<td>
<a ui-sref='hod.user'>
<input type='button' class='btn btn-xs btn-green' value='Edit' ng-click="editUserData(user.user_id)" >
</a>
</td>
<td>
<a ui-sref='hod.user'>
<input type='button' class='btn btn-xs btn-red' value='Delete' ng-click="deleteUserData(user.user_id);" >
</a>
</td>
</tr>
</tbody>

Categories

Resources