I am appending rows and columns to a table using javascript. But I need one of the classname inside the td to somethings else based on the condition inside a `$.post() response.
I did this:
let arr = ['Hermione', 'Ron', 'Harry']
arr.forEach(d=>{
$('#the_table>tbody').append(`
<tr id='tr_${d}'>
<td'>${d}</td>
<td><i id='change' class='no'></i></td>
</tr>
`);
});
const myfunc = () => {
$.post(api, json_object,
function(data, status) {
if (data.value === 'started') {
setTimeout(myfunc, 5000);
} else {
$('#change').removeClass('no').addClass('yes');
}
}, 'json');
}
myfunc();
When I do this, it is only changing the value for the first value (Hermione). But in the console.log, I can see that the data.value is not started so it should've changed to yes.
Hoe can I change it to yes for each of the rows once the condition has been passed
$('#change').removeClass('no').addClass('yes');
you need to fix this selector $('#change')
i dont know if the api return has id
but you need to select it like this
$(`tr#${data.something} #change`)
Can you provide JSfiddle or any online code setup to debug more? I could see there is first element is having a single quote that is not being ignored.
${d} should be like this ${d}
Thanks
The problem is that You are using the same id name for identifying many differents rows .
Each ID must be unique . So if you have many elements to manipulate it is better to identify them by their classname instead . Change the the the attribute ID to CLASS as illustrated below .
// I have only change the attribute id to class
let arr = ['Hermione', 'Ron', 'Harry']
arr.forEach(d=>{
$('#the_table>tbody').append(`
<tr id='tr_${d}'>
<td'>${d}</td>
<td><i class='change' class='no'></i></td>// now their identified by class name
</tr>
`);
});
const myfunc = () => {
$.post(api, json_object,
function(data, status) {
if (data.value === 'started') {
setTimeout(myfunc, 5000);
} else {
$('.change').removeClass('no').addClass('yes');
}
}, 'json');
}
myfunc();
Related
Here is my code
I am having List Array like: this is getCall.
ktsessions =
[ {"presenter":"Bharath","topic":"Angular","status":"scheduled","emailId":"bharathkumar#gmail.com"}, {"presenter":"Sayyad","topic":"Angular","status":"organized","emailId":"raheemsayyad#gmail.com"},{"presenter":"Kanchan","topic":"APS","status":"scheduled","emailId":"kanchanubey#gmail.com"} ];
<tr *ngFor = "let ktsession of ktsessions >
<td ><input type="checkbox" [disabled]='disabled'></td>
</tr>
TS code:
getktsession(){
this.service.getKtsession().subscribe(data =>{
console.log('get', data);
this.ktsessions = data;
this.ktsessions.find(user => {
if(user.presenter ==="Kanchan"){
this.disabled = true
} else {
this.disabled = false;
}
});
});
}
There are several issues here.
<tr *ngFor = "let ktsession of ktsessions > - Missing closing quote after ktsessions
<td ><input type="checkbox" [disabled]='disabled'></td> - [disabled]='disabled' should be [disabled]="ktsession.disabled". Each checkbox instance needs to have its own disabled property. [disabled]='disabled' sets each checkbox's disabled property to the disabled property of the component class instance rather than the checkbox instance.
this.ktsessions.find(user => { - Array#find is not an appropriate method to use here, even though it happens to work since you're not returning anything from the callback function and it will therefore iterate the entire array. Array#find is for searching an array for an element that matches the specified criteria and returning that element, not for iterating over an array and setting properties on each element, which is what you're doing here. Array#forEach is the appropriate method for that.
this.disabled = true and this.disabled = false - these are setting the disabled property on the component class instance (which is what this refers to), but what you need to do is set the disabled property on each user instance: user.disabled = true or user.disabled = false.
So your template should look something like this:
<tr *ngFor="let ktsession of ktsessions">
<td>
<input type="checkbox" [disabled]="ktsession.disabled" /> <!-- reference "ktsession.disabled" instead of "disabled" -->
{{ ktsession.presenter }}
</td>
</tr>
And your subscribe should look something like this:
this.getKtsession().subscribe((data) => {
this.ktsessions = data;
this.ktsessions.forEach((user) => { // <-- use forEach, not find
if (user.presenter === 'Kanchan') {
user.disabled = true; // <------------ set user.disabled, not this.disabled
} else {
user.disabled = false; // <----------- set user.disabled, not this.disabled
}
});
});
Here's a StackBlitz showing it working with those changes.
I need to give different IDs to table rows, so that when I click on the first row, it'll show "selectedRow: 1" on console. Click on the second row, it'll show "selectedRow: 2"
Thanks in advance!
Here's my code:
<tbody>
{this.testData.map((item, i) => {
return (
<tr onClick={this.handler} key={i} >
<td>{item.name}</td>
<td>{item.age}</td>
<td>{item.address}</td>
</tr>
);
})}
</tbody>
handler=(e)=>{
let selectedRow = e.target.id //doesn't work
console.log("selectedRow:", selectedRow)
}
For that to work you would need to give every tr an id attribute, but it would be better if you just straight up pass that id to the function, like so:
<tr onClick={() => this.handler(item.id)}>
You can also use the index if the items don't have unique IDs.
Now the handler function would receive the id as an argument:
handler = (selectedRow) => {
console.log("selectedRow:", selectedRow)
}
For the tr onClick we can give our id as we like like <tr onClick={this.handler(item.id)}>
and our handler function will be high level function like below, then we don't require to create function each time
handler = id => e => {
console.log(id)
}
Sample code code from sandbox
I have the following table structre:
<tr>
<td class="name">
Stock1
</td>
<td class="price">
</td>
</tr>
<tr>
<td class="name">
Stock2
</td>
<td class="price">
</td>
</tr>
Based on the names Stock1 and Stock2, I need to set the corresponding price in the next td. I am web scraping the price thru ajax and trying to set the value as follows:
For Stock1:
$(document).ready(function() {
$.ajax({
*everything else working fine*
success: function(data) {
if($('.name').html().indexOf("Stock1") != -1) {
$(this).closest('tr').find('.price').html(data);
}
}
});
});
In this scenario, this is not working, which I'm expecting to be the td tag with class name where value is Stock1. If I replace this with ".name", the code works only if there's one name td. When I have two td tags with the class name, it doesn't work.
I need to get this done as soon as the document loads, and not on some event like mouse click or hover.
this doesn't refers to td.name element nor table.
The :contains() Selector selects all elements that contain the specified text to target the td and then use can use DOM relationship to target immediate following sibling td using .next().
$('td.name:contains("Stock1")').next('.price').html(data);
or
$('td.name:contains("Stock1")').closest('tr').find('.price').html(data);
You can also use .filter()
var var1 = 'Stock1';
$('td.name').filter(function(){
return this.textContent.indexOf(var1) != -1;
}).closest('tr').find('.price').html(data);
As per comment, now you are returning an array. So need to iterate the data object and target the desired element.
var data = [{
name: "Stock1",
price: "$12"
}, {
name: "Stock2",
price: "$15"
}]
$.each(data, function(_, d){
$('td.name').filter(function() {
return this.textContent.indexOf(d.name) != -1;
}).closest('tr').find('.price').html(d.price);
})
DEMO
Use the below code in success method, assuming the data would be in the format mentioned below.
success:function(data)
// Assigning dummy values for assumption
var data = [{
stockName: "Stock1",
price: "$12"
}, {
stockName: "Stock2",
price: "$15"
}]
// Iterating throw all td which has name [class] elements
$(".name").each(function(i, obj) {
// Dummy Validation as per the mock data to repalce the data as per the stockName
if ($(this).closest('tr').find('.name').text().trim() === data[i].stockName){
$(this).closest('tr').find('.price').html(data[i].price);
}
})
});
FIDDLE
success: function(data) {
$('.name').each(function(index, element) {
if ($(element).html().indexOf("Stock1") != -1) {
$(element).closest('tr').find('.price').html(data);
}
}
}
The current implementation may not work correctly if you have multiple Stocks are present on your page. So i will suggest you to modify your server side code a bit to return back node name (like Stock1) as well as its price. So that your ajax success data will have 2 components; like data.name and data.price. first one will get used to target DOM td and later one will be used to set the price text as follows:
For Stock1:
$(document).ready(function(){
$.ajax({
url: "someBaseURL?name=Stock1"
success: function(data) {
var name = data.name; //grab the stock name
var price = data.price; //grab the stock price
//iterate over all the names and target the one associated
$('.name').each(function(){
if($.trim($(this).text()).indexOf(name) != -1)
$(this).closest('tr').find('.price').html(price);
});
}
});
});
I have a ReactClass with name Alert. Its render method returns a div with class alert alert-success or alert alert-error according to the type passed while creating element. I just want to know how to add class based on the type of alert element.
Here is my attempt:
var Alert = ReactClass({
render: function() {
return <div className="alert {this.props.type}">{this.props.message}</div>
}
});
var successAlert = React.createElement(Alert, {
type: 'alert-success'
message: 'Information saved successfully!!'
});
When JSX Template is compiled this.props.type is not converted to the class passed to element. How to achieve this ?
Looks like I have found answer to my question. We can simply do something like this:
var Alert = ReactClass({
render: function() {
return <div className={"alert " + this.props.type}>{this.props.message}</div>
}
});
Just put your classes inside Template evaluators { } in this case. Create your class string based on your props and states.
Hope this is helpful to others.
One way to accomplish this is to have a string which will contain all of your classes and then set it to the Component's className:
var Alert = ReactClass({
var yourClassName = 'alert ';
// Add any additional class names
yourClassName += this.props.type + ' ';
render: function() {
return <div className={yourClassName}>{this.props.message}</div>
}
});
or alternatively you can store your class names in an array and convert it to a class friendly string when you're ready to use it:
var Alert = ReactClass({
var yourClassArray = [];
// Add any additional class names
yourClassArray.push('alert');
yourClassArray.push(this.props.type);
var classString = yourClassArray.join(' ');
render: function() {
return <div className={classString}>{this.props.message}</div>
}
});
Take a look at the classnames package. You can do stuff like this:
className={classNames('alert', `alert-${type}`)}
or
className={classNames({
'alert': true,
'alert-success': success,
'alert-error': error
})
You can use JavaScript template literals
var Alert = ReactClass({
render: function() {
return <div className={`alert ${this.props.type}`}>{this.props.message}</div>
}
});
Your code can be written in following way:
const Alert = ({type, message}) =>
<div className={`alert ${type}`}>{message}</div>
Write in code
className={`form-control-sm d-inline per_player ${"per_player_b_" + index + "_score"}`}
and You will get
I have the following table in which I have two ids, mPoint and bPoint. I want to insert data here using html() when I hover over elements with id hydrogen or helium.
<div class="info" id="hydrogen">
<em>1</em>
H
<p>Hydrogen</p>
</div>
<div class="info" id="helium">
<em>2</em>
Li
<p>Helium</p>
</div>
<table class="propTable">
<tr>
<td>Melting Point</td>
<td id="mPoint"></td>
</tr>
<tr>
<td>Boiling Point</td>
<td id="bPoint"></td>
</tr>
</table>
Here is the JS Function
function PropElements() {
var propHydrogen = {
"m_point": "14.01",
"b_point": "20.28"
};
var propHelium = {
"m_point": "0",
"b_point": "4.22"
};
$('.info').hover(function() {
var getId = this.id;
var getPropName = "prop" + getId.charAt(0).toUpperCase() + getId.slice(1);
console.log(getPropName);
$("#mPoint").html(getPropName.m_point + " K");
$("#bPoint").html(getPropName.b_point + " K");
}, function() {
$("#mPoint").html("unknown");
$("#bPoint").html("unknown");
});
}
Here are two objects for Hydrogen and Helium. getPropName will change the name of the hovered element such that it becomes prop[hoveredElementID]. Now If I hover over div with #hydrogen, getPropName will change name to propHydrogen, which is also the name of the object. And then using html(), it should print the value of m_point and b_point at the position of specified IDs.
But its showing the value of getPropName.m_point and getPropName.b_point as unknown. I have tried putting the objects inside the function but it still returns unknown even though console is returning the exact propName that should work. I tried using innerHTML, but that returns undefined instead.
Though, If I use the name directly(propHydrogen.m_point), it prints the value correctly. What could be the problem here?
The issue is because you cannot dynamically use the value of a variable to point to another defined variable in the manner you are attempting. A better method would be to use a single object to store all information required and then access the properties of that object dynamically. Try this:
function propElements() {
var elements = {
hydrogen: {
"m_point": "14.01",
"b_point": "20.28"
},
helium: {
"m_point": "0",
"b_point": "4.22"
}
};
$('.info').hover(function() {
$("#mPoint").html(elements[this.id].m_point + " K");
$("#bPoint").html(elements[this.id].b_point + " K");
}, function() {
$("#mPoint").html("unknown");
$("#bPoint").html("unknown");
});
}
Working example
Note that by making the property names in the object match the id of the .info elements it saves a lot of unnecessary string manipulation.