react.js how to get prop form tree element - javascript

I am trying to make table cell editable after clicking on icon in another cell , for that I need to get index of element so the editor will open in the correct row , which icon belongs to.
My issue is that I dont know the way i should get the prop value of table DOM element here is code for for clearify
a part of dom tree generated with react:
<tbody>
{stepsDone.map(function(step,idx) {
let content = step;
const editing = this.state.editing;
if(editing){
content = (
<form onSubmit={this._save}>
<input type="text" defaultValue={step} />
</form>
);
}
return(
<tr key={idx}>
<td className="step" data-step={'step'+idx}>{content}</td>
<td className="icRow">
<Icon className="edit" onClick={this._showEditor} rownum={idx}/>
<Icon className="remove"/>
<Icon className="trash outline"/>
</td>
</tr>
)
},this)}
show editor function:
_showEditor(e){
this.setState({
editing:{
row:e.target.rownum
}
});
console.log(this.state.editing);
}
After execution of showedtior function console logs :
first click = null , which is normal i think
more clicks = undefined , and thats whats brings a trouble i want to receive idx from map function.
here is code from Icon.js
import React from 'react';
import classNames from 'classnames';
export function Icon(props) {
const cssclasses = classNames('icon', props.className);
return <i className={cssclasses} onClick={props.onClick}/>;
}

if you want to reveive the idx from the map function you should pass it to the function _showEditor so your code must be like this :
<Icon className="edit" onClick={this._showEditor(idx)}/>
and the function definition should be :
_showEditor = (idx) => (event) => {
this.setState({
editing:{
row:idx
}
});
console.log(this.state.editing);
}
or if you don't want to use the arrow functions for some reason, just replace
onClick={this._showEditor(idx)}
with
onClick={this._showEditor.bind(this,idx)}
and its definition becomes
_showEditor(idx){...}

Related

can't append h1 element to parent div in React?

i'm creating a simple react website that's supposed to do some calculations and find out Joules of my input values after the calculations...right now the input values are already preset but i will remove the value="" from my <input> later.
here is the .JSX component file that's the issue...one of the components.
import React, { Component } from 'react';
import Atom_icon from './cartridges.png';
class Joule_calc extends Component {
render(){
return (
<div className='Joule_div'>
<h3 style={{color:"white", textAlign:"center"}}>JOULE CALCULATOR</h3>
<label className='lab1'>WEIGHT=/GRAMS</label><br></br>
<input className='weight_inp' type='text' value="2" />
<label className='lab2'>SPEED=M/S</label><br></br>
<input className='speed_inp' type='text' value="5" />
<button className='count_button' onClick={this.Create_response}>CALCULATE</button>
<h1 className='Result_joule'></h1>
</div>
)
}
Create_response(){
console.log("creating response...")
let sum = document.createElement("h1")
sum.className = 'Result_joule'
sum.textContent = "678"
let div_panel = document.getElementsByClassName("Joule_div")
div_panel.append('Result_joule')
}
Returned_values(){
let weight_val = document.getElementsByClassName("weight_inp")[0].value;
let speed_val = document.getElementsByClassName("speed_inp")[0].value;
let final_calculation = weight_val * speed_val
return final_calculation
}
}
export default Joule_calc
so when i run my code i get
Uncaught TypeError: div_panel.append is not a function
at Create_response (Joule_calc_window.jsx:31:1)
i don't get why i can't append my new element to the div. it says it's not a function so what's the solution then? i'm new to React and web so probably it's just a noobie thing.
also i tried directly creating a h1 inside the 'Joule_div' like this.
<h1 className='Result_joule'>{"((try returning here from one of these methods))"}</h1>
but that of course failed as well. So would appreciate some help to get what's going on. i'm trying to add a number after the button click that's in h1 and in future going to be a returned number after calculating together the input values in a method.i imagine that something like
MyMethod(){
value = values calculated
return value
}
and later grab it with this.MyMethod
example
<h1>{this.MyMethod}</h1>
this is a example that of course didn't work otherwise i wouldn't be here but at least gives you a clue on what i'm trying to do.
Thank you.
You don't leverage the full power of react. You can write UI with only js world thanks to JSX. State changes triggering UI update.
I may miss some specificaiton, but fundamental code goes like the below. You should start with function component.
// Function component
const Joule_calc = () =>{
// React hooks, useState
const [weight, setWeight] = useState(0)
const [speed, setSpeed] = useState(0)
const [result,setResult] = useState(0)
const handleCalculate = () =>{
setResult(weight*speed)
}
return (
<div className="Joule_div">
<h3 style={{ color: 'white', textAlign: 'center' }}>JOULE CALCULATOR</h3>
<label className="lab1">WEIGHT=/GRAMS</label>
<br></br>
<input className="weight_inp" type="text" value={weight} onChange={(e)=>setWeight(parseFloat(e.target.value))} />
<label className="lab2">SPEED=M/S</label>
<br></br>
<input className="speed_inp" type="text" value={speed} onChange={(e)=>setSpeed(parseFloat(e.target.value))} />
<button className="count_button" onClick={handleCalculate}>
CALCULATE
</button>
<h1 className='Result_joule'>{result}</h1>
</div>
)
}
export default Joule_calc;
div_panel is an collection of array which contains the classname ["Joule_div"]. so first access that value by using indexing . and you should append a node only and your node is "sum" not 'Result_joule' and you should not use textcontent attribute because you will be gonna definitely change the value of your result as user's input value
Create_response(){
console.log("creating response...")
let sum = document.createElement("h1")
sum.className = 'Result_joule'
//sum.textContent = "678"
let div_panel = document.getElementsByClassName("Joule_div")
div_panel[0].append('sum')
}
if any problem persists , comment below

Bring Properties to the button in React js

I am trying build an booking app in react, can anyone suggest how can I bring the properties from the table to the button?
For example:
when the user click the select button on the first schedule, the schedule id and the training id of the first row, will be bringing to the select button to perform action. Any tips and helps are much appreciated in advance!
rendering table:
**booking() is my action
const bookBtn=(trainer_id, schedule_id)=>{
return(
<Button onClick={booking(trainer_id,schedule_id)} variant="danger">
Select
</Button>
)
}
const renderSchedule = (details, index) => {
return (
<tr key={index}>
<td>{details._id}</td>
<td>{details.trainer}</td>
<td>{details.date}</td>
<td>{details.startAt}</td>
<td>{details.endAt}</td>
<td>
{bookBtn(details.trainer,details._id)}
</td>
</tr>
)
}
Just pass a function to your onClick that invokes your custom handler with parameters:
const bookBtn = (trainer_id, schedule_id) => {
return(
<Button onClick={() => booking(trainer_id, schedule_id)} variant="danger">
Select
</Button>
);
}
If booking is indeed a handler, of course.

Render class conditionally in React

I'm trying to render a class conditionally. If the mapped item is blank, I'd like there to be a class that renders. Otherwise, no changes. I'm sure this very simple but I'm new at this and not sure how to identify the blank item. Is this a problem with scope? This is the code in my component:
const TableBody = (props) => {
let classes = ''
classes += (props.data.map === '') ? '' : 'collapse'
return (
<tbody>
{props.data.map((item, index) => (
<tr key={typy(item, 'sys.id').safeString || index}>
{props.columns.map(column =>
<td className={classes} role='cell' key={column.label}>{typy(item, column.path).safeObject}</td>)
}
</tr>
))}
</tbody>
)
}
All of the <td> elements are collapsed so the code I'm using above must not be properly detecting a blank value. Can anyone point me in the right direction here?
Per my comment, props.data appears to be an array. You are checking to see if props.data.map === '', which will always evaluate to false. You should probably fix that statement, otherwise the class will always be 'collapse'. Hope that helps!

How to implement an array increment function within JSX code using React.js JavaScript

I'm trying to develop a React program that changes information in a component each time the button "rectForward" or "rectBackward" is pressed. I'm passing the information in the form of an array of objects into my Body component from "importData" as seen below. That data is then converted into each object's indvidual data pieces through the map functions listed directly after render() is called. What I want to happen when the rectForward button is pressed is for the "text1" array value in Column1 to incrament by 1. The same happens when rectBackward is pressed, but I want the value to decrement. My primary difficulty is the syntax. As you can see in the statement onClick={Column1.text1=text1val[++], this was my first attempt at implementing this functionality, but the syntax is definitely incorrect. I was wondering if I could get some help formatting this
import React from "react";
import "./Body.css";
import Column1 from "./Body/Column1/Column1";
import "./Buttons.css";
import Column2 from "./Body/Column2/Column2";
import myData from "./myData";
class Body extends React.Component {
constructor() {
super()
this.state = {
importData: myData
}
}
render() {
var ID = this.state.importData.map(item => item.id)
var text1val = this.state.importData.map(item => item.text1)
var text2val = this.state.importData.map(item => item.text2)
var text3val = this.state.importData.map(item => item.text3)
return(
<div className="mainBody">
<div className="backPain">
<div className="holder">
<Column1 key={ID[0]} text1={text1val[0]}>
</Column1>
<div className="rectHolder">
<div className="rectForward" onClick={Column1.text1=text1val[++]}
<h2>Next</h2>
</div>
<div className="rectBackward">
<h2>Prev</h2>
</div>
</div>
<Column2 key={ID[0]} text2={text2val[0]} text3={text3val[0]}>
</Column2>
</div>
</div>
</div>
)
}
}
export default Body;
Thanks so much!
Simple thing i will do is keep an index in state. Than pass a function to next and prev which takes care of changing this index. and will show the values based on current state.
this.state = {
currentIndex : 0
}
HandleCurrentIndex(type){
if(type === 'inc'){
this.setState({currentIndex: this.state.currentIndex++})
} else {
this.setState({currentIndex: this.state.currnIndex-1 })
}
}
<div className="rectForward" onClick={()=>this.HandleCurrentIndex("inc")}>
<h2>Next</h2>
</div>
<div className="rectBackward" onClick={()=>this.HandleCurrentIndex('dec')}>
<h2>Prev</h2>
</div>
On side note:- This is just and example in product you should take care of index going below zero as well index exceeding limits of your data. which in turn will show undefined values. simple thing you should do is whenever it goes out of limit just reset it to default value ( 0 )

Rendering "a" with optional href in React.js

I need to render a table with a link in one of the columns, and searching for a most elegant way to do it. My main problem is - not all table rows are supplied with that link. If link is present - I need that "a" tag rendered. If not - no need for "a" tag at all. Generally speaking I would like react to handle that choice (render vs not render) depending on this.state.
This is what I have at the moment.
React.createClass({
getInitialState: function () {
return {
pipeline: this.props.data.pipeline,
liveUrl: this.props.data.liveUrl,
posted: this.props.data.created,
expires: this.props.data.end
};
},
render: function () {
return (
<tr className="posting-list">
<td>{this.state.pipeline}</td>
<td>Posted</td>
<td>
<input className="datepicker" type="text" value={this.state.posted}/>
</td>
<td>
<input className="datepicker" type="text" value={this.state.expires}/>
</td>
<td>UPDATE, DELETE</td>
</tr>
);
}
});
This results is DOM element :
XING_batch
This is not acceptable solution for me, because those blank hrefs are still clickable.
I also tried adding some logic to getInitalState(
liveUrl: (this.props.data.liveUrl !== "") ? this.props.data.liveUrl : "javascript:void;",
), which worked fine, but looks weird, and adds errors in console(Uncaught SyntaxError: Unexpected token ;)
The only way I've got left is creating 2 different components for
It's just JavaScript, so you can use any logic you like, e.g.:
<td>
{this.state.liveUrl
? <a ...>{this.state.pipeline}</a>
: this.state.pipeline}
</td>
You can choose the type of component at runtime, as well:
import * as React from "react";
const FooBar = props => {
const Component = props.href ? "a" : "div";
return (
<Component href={href}>
{props.children}
</Component>
);
};
<FooBar>Hello</FooBar> // <div>Hello</div>
<FooBar href="/">World</FooBar> // World
Take a look at spread properties:
You could use them like this for example:
var extras = { };
if (this.state.liveUrl) { extras.href = this.state.liveUrl; }
return <a {...extras} >My link</a>;
The values are merged with directly set properties. If they're not on the object, they're excluded.

Categories

Resources