When I click on a button the modal will show. The modal contains an input field. I want to set the focus to the input field inside the modal when the modal appears after clicking.
This is the button so when I click it the modal shows,
<div
class="manu-bar-card"
#click="
() => {
groupHandler.addNewgroupModal = true;
newGroupName.focus();
}"
>
This is my modal (This will show if groupHandler.addNewgroupModal is true),
<div class="modal-container" v-if="groupHandler.addNewgroupModal">
<input
ref="newGroupName"
type="text"
/>
</div>
This is the input field inside the modal I have set a ref attribute to it,
<input
ref="newGroupName"
type="text"
/>
I have registered that ref inside my <script setup> and the reactive object to show/hide modal,
const newGroupName = ref();
const groupHandler = reactive({
addNewgroupModal: false,
});
I think the reason for not focusing on the input field is modal is not mounted yet when the focus method is called. How to handle such a thing. Appreciate it if somebody could help. Thanks
Your modal should be a separate component.
Let's call it <Modal v-if="groupHandler.addNewgroupModal" />
Inside the Modal component, You can make a ref for your input, and in the onMounted function, you can call newGroupName.value.focus()
If you don't want to separate the modal to a saperate component for some reason.
You can use nextTick
<div
class="manu-bar-card"
#click="clickHandler"
>
And in the setup script.
<div
class="manu-bar-card"
#click="
() => {
groupHandler.addNewgroupModal = true;
newGroupName.focus();
}"
>
And in your setup script.
import { nextTick } from 'vue'
const clickHandler = async () => {
groupHandler.addNewgroupModal = true;
await nextTick()
newGroupName.value.focus();
}
Related
What I have achieved is when I click on the input field to show the Calendar component, and when I click outside of it to hide it. However, the problem is when I click on the icon (Calendar component) itself, I lose the focus, how to fix that? I do not want to lose the focus of the icon when I click on it.
const [isFocused, setIsFocused] = useState(false);
<form onSubmit={addTask}>
<div>
<input
id="task"
placeholder=' Add task to "Inbox" on "Tomorrow"'
className={styles.input}
onChange={handleChange}
value={taskName}
onFocus={() => setIsFocused(true)}
onBlur={() => setIsFocused(false)}
></input>
{isFocused && <Calendar />}
</div>
Calendar component
const Calendar = () => {
const [isShown, setIsShown] = useState(false);
const clickIcon = (e) => {
e.preventDefault();
setIsShown((current) => !current);
};
return (
<div>
<CalendarMonthIcon
onClick={clickIcon}
className={styles.calendar}
></CalendarMonthIcon>
{isShown && <Datepicker />}
</div>
);
};
I currently can't stop the Calendar icon from losing the focus when click on it.
You loose the focus of your input, because the click on the icon triggers the onBlur function of the input. Therefor the input looses focus and the Calendar component is beeing closed.
By adding the following function to your onBlur event, it should check if there item pressed is a child element. If that's the case the input should remain focused and the Calendar should stay open.
IMPORTANT: you have to set that onBlur function on the parent div that includes the input and calendar, otherwise the function won't work, because it looks if the click contains a child. This is also a good way to keep track if the click was outside of your component.
const closeDropdown = (event) => {
if (!event.currentTarget.contains(event.relatedTarget)) {
setIsFocused(false);
}
}
Using SlideToggle of Skeleton, I am creating a toggle switch like this.
<script lang="ts">
import { SlideToggle } from '#brainandbones/skeleton';
let is_checked: boolean = false;
</script>
<div class="page-container">
<SlideToggle bind:checked={is_monitoring}>{is_checked ? 'Activated' : 'Disabled'}</SlideToggle>
</div>
How can I get on-change event instead of polling is_checked status manually?
You can bind a change event to the toggle. This event listener will get forwarded to the underlying element in the slider.
<script lang="ts">
import { SlideToggle } from '#brainandbones/skeleton';
let handleOnChange = (e) => {
// your subroutine goes here
}
</script>
<SlideToggle on:change={handleOnChange}>Label</SlideToggle>
More info under the 'events' tab on this page of the skeleton docs.
I just discovered that the on:change event is forwarded the inner input checkbox element. Thus, on:change was already working out of the box.
Here is the discussion on Skeleton Issues.
<script lang="ts">
import { SlideToggle } from '#brainandbones/skeleton';
let checked: boolean = false;
function onChange(e: any) {
console.log(checked);
};
</script>
<SlideToggle on:checked={checked} on:change={onChange}>Label</SlideToggle>
I have created one component. in which I have a button in which once you click popup will be displayed.
data for that popup is put in another component. below is the popup.
the problem is once I am clicking on the cross(x) button at corner my popuup is not getting closed.
below is the code to launch popup.
const [statusUpdateFlag, setStatusUpdateFlag] = useState(false);
<td>
<button type="button" onClick={(event) => handleStatusUpdateClick(event)}>
click
{statusUpdateFlag && (
<StatusUpdate
certificate={props.certificate}
handleStatusUpdateClick={handleStatusUpdateClick}
closePopUp={closePopUp}
/>
)}
</button>
</td>
once user click on the button , statusUpdateFlag will be true popup will be launched.
const handleStatusUpdateClick = async (event: SyntheticEvent) => {
event.preventDefault();
setStatusUpdateFlag(true);
}
now on the close button I have just made setStatusUpdateFlag(false); . even this method is getting called. still popup is not closing.
const closePopUp = (event: any) => {
alert("closepopup called");
event.preventDefault();
setStatusUpdateFlag(false);
};
once I click X method is getting called but popup is not closing.
below is code for X button,
<button
className={styles.closeicon}
onClick={(event) => props.closePopUp(event)}
>
x
</button>
what mistake I am doing?
You have written the Popup component as children of your button, so when you click on popup close, a trigger for parent button click is also triggered so popup visible state is again set true.
const [statusUpdateFlag, setStatusUpdateFlag] = useState(false);
<td>
<button type="button" onClick={(event) => handleStatusUpdateClick(event)}>
click
{/* Issue is here */}
{statusUpdateFlag && (
<StatusUpdate
certificate={props.certificate}
handleStatusUpdateClick={handleStatusUpdateClick}
closePopUp={closePopUp}
/>
)}
</button>
</td>;
You should bring out the StatusUpdate component outside button and in my opinion for UI, outside the whole table component if possible. That should fix the issue.
"react": "^15.4.2"
I am having trouble triggering the change event from jquery for an input rendered with React.
I need to do this for some end to end testing.
here's a sandbox as a full showcase: https://codesandbox.io/s/pp1k1kq3om
with jquery already loaded.
If you run : $('#reactSlider').val(50).change() in the console, you'll notice that the change handler isn't called.
In the sandbox above there's also a pure html slider for comparison, that one works as expected (change function is called).
also tried to dispatch a new event like this:
var event = new Event('change')
var target = $('#reactSlider')[0];
target.dispatchEvent(event);
The above doesn't work either (and does work on the pure html slider).
import React from "react";
import { render } from "react-dom";
const changeHandler = event => {
alert(`react slider changed:${event.target.value}`);
};
const App = () => (
<div>
<label htmlFor="reactSlider">react-slider</label>
<input
id="reactSlider"
type="range"
onChange={changeHandler}
min={10}
max={100}
step={10}
value={20}
/>
<p>run in the console: $('#reactSlider').val(50).change()</p>
<br />
<br />
<p>Notice that for the React slider, the change event is not triggered.</p>
</div>
);
render(<App />, document.getElementById("root"));
Ok, so I've found sort of a workaround.
it looks like the onInput event can be triggered just fine. In the case of input type='range' the "input" event is triggered in the same situation as the "change" is so I was able to switch it.
Workaround would be: use onInput instead of onChange and trigger it like this:
function triggerChange(selector,evt) {
let ev = new Event(evt, { bubbles: true });
let el = $(selector)[0]
el.dispatchEvent(ev);
};
triggerChange('#reactSlider','input');
I have a <Button /> component I've created in React that abstracts out some of the styling in my application. I am using it in two different contexts - one to submit a login form, and the other to navigate to the registration page (and probably other contexts in the future).
I am trying to figure out how to pass the event handlers from the parent component to the <Button />. I want to call an onSubmit handler for the login form, but an onClick handler for the navigation button. Is this possible?
I have tried calling the component like this:
<Button text={callToAction} style={styles.callToActionButton} onClick={() => FlowRouter.go("Auth")}/>
<Button text="Go!" style={styles.registerButton} onSubmit={() => this.register(this.state.user, this.state.password)}/>
I've also tried removing the arrow function, which just causes the functions to execute when the component is loaded:
// executes event handlers on page load
<Button text={callToAction} style={styles.callToActionButton} onClick={FlowRouter.go("Auth")}/>
<Button text="Go!" style={styles.registerButton} onSubmit={this.register(this.state.user, this.state.password)}/>
In general, you can forward the onClick handler to your button class by passing it as a property. You could this make a required prop by simply defining the propTypes for your button component.
As an example, I added a small snippet that shows how it works
var StyledButton = React.createClass({
propTypes: {
// the StyledButton requires a clickHandler
clickHandler: React.PropTypes.func.Required,
// and I guess the text can be seen as required as well
text: React.PropTypes.string.required
},
render: function() {
// as you are sure you have a clickHandler, you can just reference it directly from the props
return <button type="button" onClick={this.props.clickHandler}>{this.props.text}</button>;
}
});
var MyForm = React.createClass({
getInitialState() {
return {
clicked: 0
};
},
click() {
this.setState({clicked: this.state.clicked+1});
alert('ouch');
},
secondClickHandler() {
this.setState({clicked: 0});
alert(':(');
},
render() {
// your parent component simply sets which button
return <fieldset>
<div>
<StyledButton clickHandler={this.click} text="Click me" />
{ (this.state.clicked > 0) && <StyledButton clickHandler={this.secondClickHandler} text="Not again" /> }
</div>
</fieldset>;
}
});
ReactDOM.render(
<MyForm />,
document.getElementById('container')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.0.2/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.0.2/react-dom.min.js"></script>
<div id="container">
<!-- This element's contents will be replaced with your component. -->
</div>
Also, you wouldn't in general use the submit method of a button, you would rather send the data received to a webservice, and handle any changes when the result is received. The submit kills the current website and needs to load everything anew, while with an ajax call, or a store, it can just wait for the result and then redirect the user based on the response
How we have handled this is we have a button component that renders an a tag and then we have a href prop and a onClick prop you can pass in. If its a link just pass in the href prop to the button and if you are wanting it to execute a function just pass it in an onClick prop and make sure it gets set on the a tag.
In the Button component we also setup a custom onClick function that looks like this:
_onClick: function(e) {
if (!this.props.onClick) {
return;
}
this.props.onClick(e);
}
and then on the a tag
<a href={this.props.href} onClick={this._onClick} />