Changing Font Awesome Button Style onClick - javascript

I have a button styled as a Font Awesome.
<button
onClick={this.changeLockButtonStyle}
id="LockButton"
>
<FaLockOpen />
</button>
I'm trying to find a way to change the style to <FaLockClosed /> From reading up online the only examples I see are regarding JQuery and class=”fas fa-lockclosed” toggle class. But I am using a button, not the normal icon. I have tried document.getElementById('LockButton').innerHTML= '<FaLockClosed />' but doesnt work. I'd like to avoid using JQuery if possible.

Here you go:
const [isLocked, setIsLocked] = useState(false);
return (
<button
type="button"
onClick={() => { setIsLocked(true); }}
>
{isLocked ? <FaLockClose /> : <FaLockOpen />}
</button>
);
Update:
Thats how you do it in class component.
constructor(props) {
super(props);
this.state = {
isLocked: false
};
this.lockIcon = this.lockIcon.bind(this);
}
lockIcon() {
this.setState({ isLocked: true });
}
render() {
const { isLocked } = this.state;
return (
<button
type="button"
onClick={this.lockIcon}
>
{isLocked ? <FaLockClose /> : <FaLockOpen />}
</button>
);
}

My best practice solution is using css class.
But if you can't do it , you can use display state for the 2 icons that controlled by a javascript variable.

If you using react or angular, I would just toggle the component depending on a variable set during button pushed.
Reference on how to do the toggle in react
https://stackoverflow.com/a/46425155/14167216
Here is a jQuery example.
You can set the class on the button and then check if button has class. If it has lock class then change to unlock class, and vice-versa. Check the sample code below.
function changeLockButtonStyle() {
var icon = $('#LockButton')
var hasLock = icon.hasClass('fa-lock');
if(hasLock) {
icon.removeClass('fa-lock').addClass('fa-unlock');
} else {
icon.removeClass('fa-unlock').addClass('fa-lock');
}
}
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css">
</head>
<body>
<button
onClick='changeLockButtonStyle()'
id="LockButton"
class="fa fa-lock"
>
</button>
</body>

Related

React can't figure out how to change a text through buttons onClick events

I'm new to React, Nodejs and JavaScript so bear with me.
I'm doing some practice with onClick events to change text by clicking some buttons, I have an input type="checkbox" to make the text bold when checked and vise versa, 2 buttons to increase and decrease the text size by 1+ or 1- and a span that shows the current text size (16 is my default), and finally a span with the id="textSpan" that have the text meant to be modified. I also want this buttons, the checkbox and the span with the id="fontSizeSpan" that shows the current font size to be hidden by default and when you click the text it appears on its left.
This is the code so far:
class FontChooser extends React.Component {
constructor(props) {
super(props);
this.state = {hidden: true};
this.checkInput = React.createRef();
this.hide = React.createRef();
}
toggle(){
this.setState({hidden: !this.state.hidden});
this.hide.current
}
makeBold(){
this.setState({bold: !this.state.bold});
this.checkInput.current
}
changeSize(){
this.setState({size: !this.props.size})
for(var i = this.props.size; i <= this.props.max; i++);
}
render() {
return(
<div>
<input type="checkbox" id="boldCheckbox" ref={this.hide} hidden={false} onClick={this.makeBold.bind(this)}/>
<button id="decreaseButton" ref={this.hide} hidden={false}>-</button>
<span id="fontSizeSpan" ref={this.hide} hidden={false}>{this.props.size}</span>
<button id="increaseButton" ref={this.hide} hidden={false} onClick={this.changeSize.bind(this)}>+</button>
<span id="textSpan" ref={this.checkInput} onClick={this.toggle.bind(this)}>{this.props.text}</span>
</div>
);
}
right now their hidden attribute is false so I can see them.Here's the html which is not much:
<div id='container'></div>
<script type="text/jsx">
ReactDOM.render(
<div>
<FontChooser min='4' max='40' size='16' text='You can change me!' bold='false'/>
</div>,
document.getElementById('container'))
;
</script>
So far all I have managed is for the browser console(I'm using Firefox react component addon) to confirm there is a functioning event that doesn't really work, as in when I click the text, the buttons or the input checkbox the props does change to false or true every click but that's about it.
I appreciate it if someone could guide me through this.
NOTE:
just in case nothing is imported, also I setup a local server with Nodejs
Here is an Example of what you want: https://codesandbox.io/s/mystifying-cookies-v7w3l?file=/src/App.js
Basically, I have 4 variables: text, fontWeight, fontSize and showTools.
Each button has its own task and also you can select if show or not.
In React you don't have to care about ids like in older frameworks. You can generate the elements just in the place where you are with the information which you need. So, basically, we have the 4 variables and use them wisely where we want (as styles props, as text and even as a conditional to show components). It's the magic of React and JSX.
In the code I've use hooks, part of the latest definition of React. For that my Components is functional and not a Class. it makes it easier and faster for examples and prototyping.
The tools are show by default just to let you play with it
import React from "react";
import "./styles.css";
export default function App() {
const [text, setText] = React.useState("");
const [boldFont, setBoldFont] = React.useState(false);
const [fontSize, setFontSize] = React.useState(14);
const [showTools, setShowTools] = React.useState(true);
return (
<div className="App">
<div
style={{
fontWeight: boldFont ? "bold" : "normal",
fontSize: `${fontSize}px`
}}
>
<span onClick={() => setShowTools(!showTools)}>
{text || "Text Example"}
</span>
</div>
{showTools && (
<div>
<button onClick={() => setBoldFont(!boldFont)}>Bold</button> |
<button onClick={() => setFontSize(fontSize + 1)}>A+</button>
<button onClick={() => setFontSize(fontSize - 1)}>a-</button>
<input
type="text"
value={text}
onChange={event => {
setText(event.target.value);
}}
/>
</div>
)}
</div>
);
}

React js - Show or hide a div

I am trying to show or hide a div in Reactjs using the state value in the CSS style option - display and I am using functions with hooks. I have a button and below the button a div. When i click the button i either want to hide or show the contents in the div based on whether it is currently shown or hidden.
This is the basic test code I have
import React, { useState } from "react";
function hide() {
return (
<div>
<Mycomp />
</div>
);
}
function Mycomp() {
const [dp, setDp] = useState("none");
return (
<form>
<button
onClick={() => {
setDp("block");
}}
>
Test
</button>
<div style={{ display: dp }}>Test</div>
</form>
);
}
export default hide;
I then use this hide component in my App.js file. When I click the button the new state is assigned but then the page re-renders and the initial state is loaded again almost immediately. How can I go by ensuring the new state is kept? Eventually I will create a function where if the div display or not based on the previous state.
The issue is that the button is inside a <form>. So any click on that button will submit the form and refresh the page.
Can I make a <button> not submit a form?
You need to add a type="button" to your <button>
import React, { useState } from "react";
function Hide() {
return (
<div>
<Mycomp />
</div>
);
}
function Mycomp() {
const [dp, setDp] = useState(false);
return (
<form>
<button
type="button"
onClick={() => setDp(!dp)}
>
Test
</button>
{dp && <div>Test</div>}
</form>
);
}
export default Hide;
Your code should be something like this, instead of using block and none as style we can use conditional JSX (which is more ideal approach) -:
function Mycomp(){
const[dp, toggleDp] = useState(false);
return(
<form>
<button onClick={()=>{toggleDp(!dp)}}>Test</button>
{dp && <div>Test</div>}
</form>
)
}
export default hide
A better implementation would be to have your state variable TRUE/FALSE value and based on it display the element using a conditional rendering, note e.preventDefault in the button handler to stop the refresh/redirect, here is a working snippet, also a codesandbox:
const { useState, useEffect } = React;
function App() {
return (
<div>
<Mycomp />
</div>
);
}
function Mycomp() {
const [dp, setDp] = useState(true);
return (
<form>
<button
onClick={(e) => {
e.preventDefault();
setDp(!dp);
}}
>
Test
</button>
{dp && <div>Test</div>}
</form>
);
}
ReactDOM.render(<App />, document.getElementById("react-root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="react-root"></div>

Using ReactModal button with Href, not working. Unsure why

I am fairly new to react and have redone my personal site in react. The issue I am running into is my button that links (with href) to my JSfiddle for each portfolio demo is not working. I am not sure if I did not bind correctly or what exactly the issue is other than when the modal is open, the Demo button does not work. Close modal button works fine. Please see code below.
import React from 'react';
import ReactModal from 'react-modal';
class Project extends React.Component {
constructor () {
super();
this.state = {
showModal: false
};
this.handleOpenModal = this.handleOpenModal.bind(this);
this.handleCloseModal = this.handleCloseModal.bind(this);
}
handleOpenModal() {
this.setState({ showModal: true});
}
handleCloseModal() {
this.setState({ showModal: false});
}
componentWillMount() {
ReactModal.setAppElement('body');
}
render() {
const { details } = this.props;
return (
<li className="Project">
<div onClick={this.handleOpenModal}>
<img className="Project-image" src={'projects/' + details.image} alt={details.name}/>
<div className="Project-overlay">
<p>{details.name}</p>
</div>
</div>
<div >
<ReactModal
isOpen={this.state.showModal}
contentLabel="This is my Modal"
shouldCloseOnOverlayClick={true}
onRequestClose={this.handleCloseModal}
>
<div className="modal-header">
<h3>{details.name}</h3>
</div>
<div className="modal-body">
<img className="Project-image" src={'projects/' + details.image} alt={details.name} />
<p className="desc-body">{details.desc}</p>
<p className="desc-body">{details.link}</p>
</div>
<div className="modal-footer">
{ details.havLink && <button className="button" href={details.link}>Click for Demo!</button> }
<button className="button" onClick={this.handleCloseModal}>Close Modal</button>
</div>
</ReactModal>
</div>
<div className="Project-tag">
<p>{details.tag}</p>
</div>
</li>
)
}
}
const props = {};
export default Project;
The issue is in the first line of the "modal-footer" class. This button will show if the havLink property is true. This data is being exported from another JS file. Everything else (image, description, modal title) all import correctly, even the link I set imports correctly but when the button is pushed nothing fires as I expected. I do not see any errors in my React dev tools either.
{details.link} as an href is not routing me to the specified link. The link will show up in the paragraph tag though (just to see if correct link populated).
Let me know if anything else is needed, I am hoping the solution is as simple as an incorrect binding. Thank you in advance!
<button> does not have the href attribute. You should be using an anchor element <a>. To the anchor you can pass whatever class or style you want to make it look like a button, but it's still an anchor element, not button.

Semantic React Modal weird height behavior

Here is the problem I am having when using the semantic UI React modal: I do as shown on their website, but weirdly my Modal moves around like in this GIF of what is happening.
I have no idea how to fix this. Here is my code:
class Success extends React.Component {
constructor () {
super();
this.closeModal = this.closeModal.bind(this)
this.state = {
Modalopen: true,
Orders: "",
urlparameter: qs.parse(location.search.replace(/^.*?\=/, ''))
}
}
closeModal () {
this.setState({Modalopen: false})
this.props.history.pushState(null, "/")
}
render () {
return (
<Modal open={this.state.Modalopen}>
<Modal.Header>Success!</Modal.Header>
<Modal.Content image>
<Image wrapped size='medium' src='http://semantic-ui.com/images/avatar2/large/rachel.png' />
<Modal.Description>
<Header>Thank you</Header>
<p>bla bla bla</p>
<Button color='green' onClick={this.closeModal} inverted>
<Icon name='checkmark' /> Got it
</Button>
</Modal.Description>
</Modal.Content>
</Modal>
);
}
}
What might be causing this issue? Thank you.
I had the same problem today when trying to create a custom 'fullscreen' modal.
This is the line causing us trouble...
https://github.com/Semantic-Org/Semantic-UI-React/blob/master/src/modules/Modal/Modal.js#L255
If the modal height is greater than or equal to window.innerHeight, it adds the class scrolling which comes with a bunch of styles.
setPositionAndClassNames then appears to be called recursively on line 271, which is probably causing the weird looping behaviour.
Dirty fix
I'm adding margin-bottom: 1px to my modal to make sure it's a tiny bit less than window.innerHeight.
Long term solution
I'll open a PR into semantic-ui-react and see what they say...
UPDATE
I have a PR open at https://github.com/Semantic-Org/Semantic-UI-React/pull/3024 with a suggested fix.
UPDATE
That's merged and now part of Semantic UI React.
In my case, it create Modal normally.
Here is the test code(ES5/webpack) :
[index.html]
<!DOCTYPE html>
<html lang="ko-KR">
<head>
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.2.2/semantic.min.css"></link>
</head>
<body>
<div id="wrap"></div>
<script src="dist/app.js"></script>
</body>
</html>
[app.jsx]
var React = require('react');
var ReactDOM = require('react-dom');
var Semantic = require('semantic-ui-react');
var Button = Semantic.Button;
var Header = Semantic.Modal.Header;
var Image = Semantic.Image;
var Modal = Semantic.Modal;
var Icon = Semantic.Icon;
var IndexPage = React.createClass({
getInitialState : function() {
return {
Modalopen: true,
Orders: "",
//urlparameter: qs.parse(location.search.replace(/^.*?\=/, ''))
}
},
closeModal: function() {
this.setState({Modalopen: false})
//this.props.history.pushState(null, "/")
},
render : function () {
return (
<Modal open={this.state.Modalopen}>
<Modal.Header>Success!</Modal.Header>
<Modal.Content image>
<Image wrapped size='medium' src='http://semantic-ui.com/images/avatar2/large/rachel.png' />
<Modal.Description>
<Header>Thank you</Header>
<p>bla bla bla</p>
<Button color='green' inverted>
<Icon name='checkmark' /> Got it
</Button>
</Modal.Description>
</Modal.Content>
</Modal>
);
}
});
ReactDOM.render(<IndexPage/>, document.getElementById('wrap'));
Image of Result by the upper code
If you get the error continually,
Please add the html/js files more detail with Codepen to test like your situation.

Easier way to to disable link in React?

I want to disable Link in some condition:
render() {
return (<li>{this.props.canClick ?
<Link to="/">Test</Link> :
<a>Test</a>}
</li>)
}
<Link> must specify to, so I can not disable <Link> and I have to use <a>
You could just set set the link's onClick property:
render () {
return(
<li>
{
this.props.notClickable
? <Link to="/" className="disabledCursor" onClick={ (event) => event.preventDefault() }>Link</Link>
: <Link to="/" className="notDisabled">Link</Link>
}
</li>
);
};
Then disable the hover effect via css using the cursor property.
.disabledCursor {
cursor: default;
}
I think that should do the trick?
Your code already seems quite clean and slim. Not sure why you want an "easier" way. I'd do it exactly how you're doing it.
However, here are a few alternatives:
Using pointer-events
This one is probably as short and sweet as you can get it:
render() {
return (<li>
<Link to="/" style={this.props.canClick ? {pointerEvents: "none"} : null}>Test</Link>
</li>)
}
Using onClick listener
As an alternative, you could use a generic <a> tag and add an onClick listener for the condition. This is probably better suited if you have lots of links that you want to control their state because you could use the same function on all of them.
_handleClick = () => {
if(this.props.canClick) {
this.context.router.push("/");
}
}
render() {
return (
<li>
<a onClick={this._handleClick}>Test</a>});
</li>
);
}
The above will work assuming you are using context.router. If not, add to your class:
static contextTypes = {
router: React.PropTypes.object
}
Better version of OP code
As I mentioned above, I still think your approach is the "best". You could replace the anchor tag with a span, to get rid of the styling for a disabled link (e.g pointer cursor, hover effects, etc).
render() {
return (<li>{this.props.canClick ?
<Link to="/">Test</Link> :
<span>Test</span>}
</li>)
}
A good solution is using onClick() with event object. just do this in your jsx:
<Link to='Everything' onClick={(e) => this._onClick(e)}
and in your _onClick function:
_onClick = (e) => {
e.preventDefault()
}
Complete Example in React:
import React, { Component } from 'react'
import {Link} from 'react-router-dom'
export default class List extends Component {
_onClick = (e) => {
e.preventDefault()
}
render(){
return(
<div className='link-container'>
<Link to='Something' onClick={e => this._onClick(e)}
</div>
)
}
}
Just making the URL null seems to do the trick:
const url = isDisabled ? null : 'http://www.stackoverflow.com';
return (
<a href={url}>Click Me</a>
);
In short easier way to disable link in React?
<Link to="#">Text</Link>
I think you should you atrribute to=null to set disable a link.
<Link to=null />
Your code:
render() {
return (<li>
<Link to={this.props.canClick?'/goto-a-link':null} >Test</Link>
</li>)
}
Passing # in to prop to the Link should do the trick for you
You can define link as per your requirement. if you want to disable it just pass # in props.link
render() {
return (<li><Link to={props.link}>Test</Link></li>);
}
I didn't like any of the answers. Surprisingly, if you are using bootstrap, assigning the class disabled will make the link inactive. So, no need to change the path to # or anything.
<Link to='something/else' className='nav-link disabled'>Transactions Detail</Link>
Use this in your link tag. I'm using it in functional component and it's working fine.
<Link style={{pointerEvents: 'none'}}>
You can conditionally set the to prop of the Link component. When you set it to #, the link would be disabled.
render() {
return (
<li>
{
<Link to={`${this.props.canClick ? '/' : '#'}`}>Test</Link>
}
</li>
)
}

Categories