I am looping over some data and rendering it into the browser like
{paymentPeriods.map((item, index) => {
return (
<>
<div
className={`payment-card ${
type.toLowerCase() == item.type.toLowerCase()
? "payment-card-active"
: ""
}`}
key={index}
onClick={() => {
setPaymentPeriodValue(item);
}}
>
<div
className={`payment-card-title ${
type.toLowerCase() == item.type.toLowerCase()
? "payment-card-title-active"
: ""
}`}
>
{item.type.toLowerCase() == "annual"
? "ANNUAL"
: "MONTHLY"}
</div>
<div className="payment-card-body">
//Some dummy text
</div>
{item.type.toLowerCase() != "annual" && (
<p className="installments_check" onClick={()=>alert('123')}>
Verifique todas as outras parcelas
</p>
)}
</div>
</>
);
})}
As you can see upon clicking on div, I am running a function
setPaymentPeriodValue(item);
which is used to set the div as active so that it is highlighted upon click and the info get stored in my react state locally, now there is also a text inside my div which i am showing like
{item.type.toLowerCase() != "annual" && (
<p className="installments_check" onClick={()=>alert('123')}>
Verifique todas as outras parcelas
</p>
)}
So on clicking on this text (it is inside the main div) the alert is seen by the user but then it also runs setPaymentPeriodValue function which sets div to the active state, and i do not want this as i only need to show the alert on click of the text
Thanks
You can do it by using stopPropagation method of the Event (this method stops the bubbling of an event to parent elements). like this:
{
item.type.toLowerCase() != "annual" && (
<p className="installments_check" onClick={(e)=>{ alert('123'); e.stopPropagation(); } }> Verifique todas as outras parcelas </p>
)
}
Related
I have an array of objects, where each object has a textValue, an active, info, etc. This arrangement I walk through and show buttons for each element. To each button inside I add a div and inside 3 paragraphs, I'm trying to add classes and display some of the paragraphs by condition to each button. I add an event to the button and pass it an id, with this I set the active to true and show information, this for each different id. Clicking on a button makes an active class and shows a quantity, clicking outside or on the button itself eliminates the class and the quantity (p), when I click on a button information opens, here I have a button that when clicking, the div with the information is hidden (I already do this) and I want to keep the class visible and the paragraph visible, I'm using conditionals for this, but I can't do it, this is the code:
<button
v-for="filter in addedFilters"
:key="filter"
:value="filter.textValue"
#click="(e) => {openInfoFiltro(filter, e)}"
:class="{'filter-active': filter.active && !optionButtonValue.includes(filter.textValue), 'active-filter-options': filter.active && optionButtonValue.includes(filter.textValue)}">
<div>
<p v-if="filter.active && filter.textValue !== 'Uso de suelo' && filter.textValue !== 'Amenidades' && filter.textValue !== 'Clasificación de la tierra' & filter.textValue !== 'Vocaciones'" class="m-0">
{{ $filters.numeralFormatBtnInfo(filter.info[0]) }} - {{$filters.numeralFormatBtnInfo(filter.info[1]) }}
</p>
<p v-else-if="filter.active || filter.textValue === 'Uso de suelo' && filter.textValue === 'Amenidades' && filter.textValue === 'Clasificación de la tierra' && filter.textValue === 'Vocaciones'" class="m-0 amount">
<span v-if="filter.info">({{filter.info === 0 ? '' : filter.info }})</span>
</p>
<p class="m-0">{{filter.textValue}}</p>
</div>
</button>
function when clicking on the button and setting the active of the object to true
const openInfoFiltro = (id,e) => {
selectedFilter.value = addedFilters.value.find(val => val.textValue === id.textValue);
console.log(selectedFilter.value)
if(selectedFilter.value){
selectedFilter.value.active = !selectedFilter.value.active
}
}
array where i have the different text Value
const optionButtonValue = ['Uso de suelo', 'Amenidades', 'Clasificación de la tierra', 'Vocaciones' ]
In another component I go through provide and reject the ref, where I pass the selected filter (selectedFilter) and here I have a function where when clicked, I want the button to remain active and depending on the optionButtonValue, show one paragraph or the other, but leave it active, right here I pass the active to false to hide the information of each button
const showResults = () => {
console.log('Mostrar resultados')
landsStore.lands = []
landsStore.landsadd = []
selectedFilter.value.active = false
landsStore.fetchLands('', { filters: filtersStore.getAllFiltersAlgoliaFormat, facetFilters: filtersStore.getAllFacetFilterFormat })
}
Actually, v-if waits from you only true and false. But you are use in v-if text definition. This is not correctly. Firstly, you can change v-if only conditionally like v-if="{filter.active || filter} " also in your p tag you can type define directly change text {{ filter.active && 'bla bla' }}
i am trying to make my button disappear if my textarea is empty
until now i have made some code for it but i still cant do it
in the code i am trying to make the css dynamic by having it change accoring to some ternery condition id the condition is met the css will allow the button to work and if not the other css class will turn the button off
my problem is that i want the on/off condition to work only when the textfield has more than one letter ( is not empty ) this will help me in my posting application as it will not post any empty posts instead only posts with letters and words ( non empty textarea) will post
here is the code:
function PostingNow() {
const [post, setPost] = useContext(Mycontext);
const tw = useRef('')
const[count,setCount] = useState(false)
return (
<div >
<textarea placeholder='whats up?' className="box" ref={tw}></textarea>
<button className={count?'tweetbutton':'unclickable'} >
Tweet
</button>
</div>
{post.map((post, i) => (
<Postingcomponent name ='user name'image={Photo} key={i} postContent={post}/>
))}
</div>
);
}
export default PostingNow
You can conditionally render your button in the jsx.
First make your textarea a controlled component so you have access to its state.
Then write
{textAreaText && <button ... />}
Make the textarea to be a controlled input
const [textarea, setTextarea] = useState("")
...
<textarea onChange={e => setTextarea(e.target.value)}>{textarea}</textarea>
Then for the button:
{textarea && <button ... />}
For better UX, it's recommended to disable the button instead of removing it from DOM.
<button disabled={!textarea} ... />
If you make the TEXTAREA tag something like:
<textarea placeholder='whats up?' className="box" ref={tw} class='unclickable'
onkeyup="fixPostButton(this, 'postButton', 'unclickable', 'tweetbutton');">
And make the BUTTON:
<button id="postButton" class="unclickable">Tweet</button>
Then this javascript will change the class after each keystroke:
<script>
function fixPostButton(txta, butn, isempty, notempty) {
var classX = (txta.value == '') ? isempty : notempty ;
document.getElementById(butn).className = classX; }
</script>
I have created following design:
Here is the react js code:
{this.props.BetSlipDataObj.betDetails.data.map(
(value, index) => {
<div className="d-flex justify-content-end">
<button
className="info-button"
data-toggle="collapse"
href="#collapseExample"
role="button"
aria-expanded="false"
aria-controls="collapseExample"
// onClick={
// value.betId != null
// ? _this.getBetIdDetails(value.betId)
// : value.childId != null
// ? _this.getBetIdDetails(value.childId)
// : ""
// }
>
</div>
})}
Here I am trying following task
If I click on one button it should expand the box
But if I click on one button all boxes are expanding.
If I call some method on click its getting called infinitely
Can someone help me to correct the code ?
You can call a function on button click. I think it was calling infinitely because you were not passing a reference to the function.
{this.props.BetSlipDataObj.betDetails.data.map(
(value, index) => (
<div className="d-flex justify-content-end" key={index}>
<button
className="info-button"
data-toggle="collapse"
href="#collapseExample"
role="button"
aria-expanded="false"
aria-controls="collapseExample"
onClick={
value.betId != null
? () => _this.getBetIdDetails(value.betId)
: value.childId != null
? () => _this.getBetIdDetails(value.childId)
: () => {}
}
>
</div>
)
)}
You were also missing the key prop on div
EDIT:
One button is opening all the boxes because they all have the same IDs and controls.
To make the IDs and controls unique, you can do something like this:
{this.props.BetSlipDataObj.betDetails.data.map(
(value, index) => (
<div className="d-flex justify-content-end" key={index}>
<button
className="info-button"
data-toggle={`collapse${index}`}
href={`#collapseExample${index}`}
role="button"
aria-expanded="false"
aria-controls={`collapseExample${index}`}
onClick={
value.betId != null
? () => _this.getBetIdDetails(value.betId)
: value.childId != null
? () => _this.getBetIdDetails(value.childId)
: () => {}
}
>
</div>
)
)}
The solution seems pretty straightforward. You're directly executing a function in the onClick. That's why all of them are getting executed. You just need to change the onClick as follows:
onClick = { () => {
if(value.betId != null){
_this.getBetIdDetails(value.betId)
} else if (value.childId != null){
_this.getBetIdDetails(value.childId)
} else {return ""} }
To each div you need to give unique id, may be primary key of that row, and when that button is clicked pass the id to the opening function, and append that to id of that div to open. Hope it helps. This will go like this:-
onclick=handler(1)
div id should be like this:- open1, open2
handler should be like this:-
handler(id) => idofelement+id open
I have an array that contains Title1, Title2, Title3, all the way to Title8. If that item is not empty I want to display with it's corresponding information. Currently that works.
However I want to add a button that will allow me to display all fields. For example let's say Title1 through Title3 is not null. It will show that (which it currently does). I want to add a button that when clicked will display all Titles 1-8.
Here is my current code. In the code below I'm only showing 4 if statements and removed all content to save space:
{ this.state.showExtraRows? <div>
{ this.state.Product[0].Title1 ?
<div>
//Display some fields here
</div>
: null
}
{ this.state.Product[0].Title2 ?
<div>
//Display some fields here
</div>
: null
}
{ this.state.Product[0].Title3 ?
<div>
//Display some fields here
</div>
: null
}
{ this.state.Product[0].Title4 ?
<div>
//Display some fields here
</div>
: null
}
</div>
: null
}
<button className={styles.btn}
type="button"
onClick={()=>{this.setState({showExtraRows:!this.state.showExtraRows})}}>
{ this.state.showExtraRows? 'Hide Rows' : 'Show Rows'}
</button>
I'm not too sure if I'm supposed to wrap the whole thing in the this.state.showExtraRows? statement.
I think it's better to use a map function here
const productWithTitles = this.state.Product.filter((Product) => !!Product.title);
return (
<div>
{this.state.showExtraRows && (
<div>
{productWithTitles.slice(0, 3).map((product) => {
return (
<div>
//Display some fields here
</div>
);
})}
</div>
)}
</div>
);
Sorry if the title is vague. My problem is that I have three button tags, and for each tag I want it to send a unique argument to selectSupplier(). However no matter what button I press selectSupplier() only receives the last value ("ultramar") as an argument.
selectSupplier(supplier){
this.props.Obj.supplier = supplier
}
render() {
//console.log("SUPPLIER", this.props)
return (
<div>
<button onClick={this.showMenu}>
Select Supplier
</button>
{
this.state.showMenu
? (
<div
className="menu"
ref={(element) => {
this.dropdownMenu = element;
}}
>
<button value="Husky" onClick={this.selectSupplier("Husky")}> Husky </button>
<button value="Shell" onClick={this.selectSupplier("Shell")}> Shell </button>
<button value="Ultramar" onClick={this.selectSupplier("Ultramar")}> Ultramar</button>
</div>
)
: (
null
)
}
</div>
);
You can call like this :
this.selectSupplier.bind(this,"Husky");