How to put an onClick event on an font awesome icon in react? - reactjs

I am trying to set an onClick event on a fontawesome icon but it doesnt work when I do this.
<i class="fab fa-accessible-icon" onClick={this.removeItems}></i>
It only works when I put the onClick on p tags or h tags like this.
<h1 onClick={this.removeItems}><i class="fab fa-accessible-icon"></i></h1>
It is not possible to set event on icon itself? Doing this the second way is causing me style errors.
Edit: I did change the class to className, my bad. but its still not working and currently im bypassing it using around the icon and having the onClick on the span.

Here you can look into react docs which explains to use className instead of class.
Also wrap your <i> tag in button tag and use onClick() function there.

Well it should work like below...
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet" integrity="sha384-wvfXpqpZZVQGK6TAh5PVlGOfQNHSoD2xbE+QkPxCAFlNEevoEH3Sl0sibVcOQVnN" crossorigin="anonymous">
<i class="fa fa-cog" onClick="console.log('Clicked')"></i>
If its not try to wrap your icon into a button
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet" integrity="sha384-wvfXpqpZZVQGK6TAh5PVlGOfQNHSoD2xbE+QkPxCAFlNEevoEH3Sl0sibVcOQVnN" crossorigin="anonymous">
<button><i class="fa fa-cog" onClick="console.log('Clicked')"></i></button>

Perhaps try
<i className="fab fa-accessible-icon" onClick={this.removeItems}></i>
I was able to get
<i onClick={doSomething}>Testing</i>
to handle the click event, but it was rendered as jsx (ala render() method) -- assuming you are doing likewise.

You are confusing JSX with HTML. The i tag you have in your code is not plain html tag it is a javascript object(read more about jsx here). React takes care of binding the events for you, don't worry if you can't see onClick in your html.

Change class attribute to ClassName
<i className="fab fa-accessible-icon" onClick={this.removeItems}></i>
I think its work. check the demo https://stackblitz.com/edit/react-nh2bqu

If you're using react-fontawesome, you can use the FontAwesomeIcon component, and set both an id and an onClick:
<FontAwesomeIcon id={yourIdGoesHere} icon={faEdit} onClick={this.editItem} />
...
editItem = event => {
let idOfClickedIcon = event.currentTarget.id
...do something with the item associated with the id
}

Related

How to find the css selector of a href/a/button

I am trying to find out css selector for "Clear" button, as mentioned in below script:
<a href="" class="slds-button slds-button--neutral search-button"
ng-click="vm.clearFilter()" style="">Clear</a>
I have tried :
a[href*="Clear"]
a:contains('Clear')
a[*'Clear'*]
I am expecting to get a click on "Clear" button.
If your are trying to reach that button with the text, then it's not possible.
How about putting an id:
a#clearButton{
background:red
}
<a href="" id="clearButton" class="slds-button slds-button--neutral
search-button">Clear</a>
I see you use AngularJS, the id can be added via the code

Responsive navigation menu with React and Bootstrap - hamburger isn't working

I created a simple navigation menu with Bootstrap. It's working fine in pure javascript, but when adapting it into react, the hamburger icon doesn't function (nothing happens on click). I installed bootstrap with
npm install --save bootstrap
And then added the bootstrap css to index.html in the public folder:
link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/css/bootstrap.min.css" integrity="sha384-WskhaSGFgHYWDcbwN70/dfYBj47jz9qbsMId/iRN3ewGhXQFZCSftd1LZCfmhktB"
My jsx is as follows:
<nav className="navbar navbar-expand-sm navbar-dark bg-dark">
<div className="container">
<button className="navbar-toggler" data-toggle="collapse" data-target="#navbarNav"><span className="navbar-toggler-icon"></span></button>
<div className="collapse navbar-collapse" id="navbarNav">
<ul className="navbar-nav ml-auto">
<li className="nav-item">
<Link to="/app/portfolio" className="nav-link">PORTFOLIO</Link>
</li>
<li className="nav-item">
<Link to="/app/about" className="nav-link">ABOUT</Link>
</li>
<li className="nav-item">
<Link to="#create-head-section" className="nav-link" style={{fontStyle: 'italic'}}>Personal art</Link>
</li>
<li className="nav-item">
<Link to="#share-head-section" className="nav-link">CONTACT</Link>
</li>
</ul>
</div>
</div>
</nav>
Again, everything looks fine except that the hamburger icon is not functioning.
The bootstrap show class is used to display the collapsible menu items. So, the task is to simply add the show class conditionally on click of the hamburger icon.
Just follow these simple steps to achieve this functionality.
Add a showCollapsedMenu(the name is up to you) property with initial value of false in your state like this:
state={
showCollapsedMenu: false
}
Then declare a function like this which when called will reverse the current state:
toggleMenu = () => {
this.setState({
showCollapsedMenu: !this.state.showCollapsedMenu
})
}
The above function will be called whenever the hamburger icon is clicked. So implement the onCLick method on the hamburger icon like this:
<button
className="navbar-toggler"
type="button"
onClick={this.toggleMenu} // <=
data-toggle="collapse"
data-target="#navbarNav">
<span className="navbar-toggler-icon"></span>
</button>
Now create a const show which will conditionally add the show class depending on the state of showCollapsedMenu:
const show = (this.state.showCollapsedMenu) ? "show" : "" ;
Now finally add this show to the div with collapse navbar class like this:
<div className={"collapse navbar-collapse " + show} id="navbarNav">
Note: Mixing jQuery with React is not recommended as they both manipulate the DOM differently. While it may seem an easy solution, it might result in bigger problems.
Bootstrap events require jQuery, Popper and Bootstrap.js source. That page will also let you know which components require JS. You can include jQuery, Popper and bootstrap.js in the index.html file, where you load your bundle. Either add that, or simply check out Reactstrap, which implements Bootstrap components in React.
According to https://www.npmjs.com/package/bootstrap#whats-included, the npm version of Bootstrap doesn't include jQuery, but the navbar component needs it, so you might need to add https://www.npmjs.com/package/jquery to your dependencies.

How to work around jsx-a11y/no-static-element-interactions restriction?

I used the following jsx to construct an entry in a FAQ table:
<li key={faqKey} className={styles.entry} onClick={handleExpandFn}>
<div>
<span className={`icon-next ${questionClassname}`} />
<span className={styles['question-text']}>{faqEntry.question}</span>
</div>
{faqEntry.answer}
</li>
The idea is that when a user click on the entry, it will toggle the open state of the entry. In the other word, when a user clicks on an open FAQ entry, it will close it. Otherwise it will open it.
However the li tag triggers this eslint violation: Visible, non-interactive elements should not have mouse or keyboard event listeners jsx-a11y/no-static-element-interactions
Unfortunately I don't think there is alternative way to the above html markup.
Since it is jsx, it also does not allow override such as // eslint-disable-line jsx-a11y/no-static-element-interactions (The inline comment will be printed out to the web page)
So how I can work around it? Happy to use different jsx markup or jsx eslint override
For those who are looking for a workaround, use role="presentation" in your tag.
Here's how you could revise the markup to be semantically appropriate and get the onclick off the <li>
<li key={faqKey} className={styles.entry}>
<h3>
<button type='button' onClick={handleExpandFn}>
<span className={`icon-next ${questionClassname}`} />
<span className={styles['question-text']}>{faqEntry.question}</span>
</button>
</h3>
<div className='add_a_panel_class_name_here'>
{faqEntry.answer}
</div>
</li>
So with the above:
the <h3> will make the titles of the FAQs easily searchable by screen reader users that are navigating by headings
placing the <button> inside of the <h3> gives you the appropriate element to attach a click event to (you want to use a button here because you're toggling state. an <a> should be used if you were going to a new page. You also don't need to add a tabindex to a button as they are inherently focusable).
There are some additional steps you'd likely want to implement, using ARIA expanded and controls attributes on the button, but the above should get you to a good base for moving beyond your error.
You could put eslint-disable-line in the jsx
<li // eslint-disable-line jsx-a11y/no-static-element-interactions
key={faqKey}
className={styles.entry}
onClick={handleExpandFn}
>
<div>
<span className={`icon-next ${questionClassname}`} />
<span className={styles['question-text']}>{faqEntry.question}</span>
</div>
{faqEntry.answer}
</li>
Another option, add role='presentation'
<li
key={faqKey}
className={styles.entry}
onClick={handleExpandFn}
role='presentation'
>
<div>
<span className={`icon-next ${questionClassname}`} />
<span className={styles['question-text']}>{faqEntry.question}</span>
</div>
{faqEntry.answer}
</li>
One solution I can remember is to use an anchor element with tab-index.
<a style={{display: 'list-item'}} tabIndex={-42} key={faqKey} className={styles.entry} onClick={handleExpandFn}>
<div>
<span className={`icon-next ${questionClassname}`} />
<span className={styles['question-text']}>{faqEntry.question}</span>
</div>
{faqEntry.answer}
</a>
if you are trying to implement menu using li then the right solution is using role="menuitem" in your li tags.
More details about it: https://w3c.github.io/aria/#menuitem
To overcome or avoid this error in ES Lint.
You can use three things based on your needs and requirements
aria-hidden="true" - will remove the entire element from the accessibility API
role= "presentation" - The presentation role is used to remove semantic meaning from an element and any of its related child elements.
role= "none" - will remove the semantic meaning of an element while still exposing it to assistive technology.
There are limitations as well:
Hide content from assistive technology
Cannot be used on a focusable
Element cannot be used on the parent of an interactive element
You can actually add the eslint override as a comment in JSX.
You have to nest the comment inside of braces {}, so that it will be interpreted as JavaScript. Then, of course, since it is a JavaScript comment, it will not be rendered in the JSX.
Depending on your style preference, you can either do it on the line directly before the code
{/* eslint-disable-next-line */}
<li key={faqKey} className={styles.entry} onClick={handleExpandFn}>
or, at the end of the same line
<li key={faqKey} className={styles.entry} onClick={handleExpandFn}> {/* eslint-disable-line */}
Check out the docs for more information on using JavaScript inside of JSX.
use
aria-hidden="true"
on non interactive element tag. like
<span aria-hidden="true" onClick={() => void}>Text</span>
Instead of rolling my implementation of faq table with collapse/expand interactive feature, I replace it with react-collapsible.
It of course gets rid of the jsx-a11y/no-static-element-interactions as a result.

Simulate a click on span tag in enzyme

I have a span tag in my component and I need to click it using enzyme
<span className="lock">
<span onClick={[undefined]} id="lock">
<i className="fa fa-lock" />
Reserve this chat
</span>
</span>
Here is my test
it('simulating reservechat click ...',()=>{
const wrapper=shallow(<ReserveChat activeConversation={conversation1} />);
const button=wrapper.find('span').last();
button.simulate('click');
});
I am confused to find what to click,usually there will be some div class or other findable tags
Maybe you can use a ref attribute on your span element, like :
<span onClick={this.props.lockConversation} ref='chat-button'>
And then, I'm not that familiar with enzyme, but seems to me that something like
const button=wrapper.ref('chat-button');
should work, if I read their doc properly.

How to set ngClass based on Bootstrap's collapse?

I use collapse plugin from Bootstrap, and i also want to change class for another element accordingly (change class of fa-icon).
I also use AngularJS and i liked the idea of using condition in ngClass like this:
<i ng-class="collapsableItemId.hasClass('in') ? 'fa-chevron-up' : 'fa-chevron-down'">
When item is not collapsed bootstrap adds in class to it. I want to try to change icon based on class presence in collapsable item, but did not succeed in it. In bootstrap manual there is also mentioned that collapse generates events which i could probably use, but i also do not know how.
It should work like this. Use ng-click on the collapse toggle element to change some other scope var and then use that var in the ng-class of the icon..
<a href="" data-toggle="collapse" data-target=".collapse" ng-click="isOpen=!isOpen">
<i class="fa" ng-class="(isOpen) ? 'fa-chevron-up' : 'fa-chevron-down'"></i>
</a>
<div class="collapse in">
I'm the collapsible element.
</div>
http://www.bootply.com/nqLf22HCli
<i ng-class="{'fa-chevron-up': abc.isOpen ,'fa-chevron-down': !abc.isOpen }"></i><div ng-show="abc.isOpen">Hi..This div will be show hide and icon will be change accordingly</div>
Use ng-click on collapsing header and put that div which you want to collapse
add ng-show="abc.isOpen".

Resources