Let's continue with the update name example, this time we want to disable the "Change" button when the input is empty or when the value hasn't changed.
We take 06 MoveBackToStateless/ as reference.
Summary steps:
- Add a condition to disable the button.
Install Node.js and npm (v6.6.0 or newer) if they are not already installed on your computer.
Verify that you are running at least node v6.x.x and npm 3.x.x by running
node -vandnpm -vin a terminal/console window. Older versions may produce errors.
-
Copy the content from 06 MoveBackToStateless/.
-
Let's start by adding a condition to disable the button whenever the input field is empty. Replace only the input tag in ./src/nameEdit.tsx with the following code:
<div>
<label>Update Name:</label>
<input value={props.editingUserName}
onChange={(e) : void => props.onEditingNameUpdated((e.target as HTMLInputElement).value)} />
- <button className="btn btn-default" onClick={props.onNameUpdateRequest}>Change</button>
+ <button
+ className="btn btn-default"
+ onClick={props.onNameUpdateRequest}
+ disabled={!props.editingUserName}
+ >Change</button>
</div>- Now comes the tricky part: to detect when
userNamehas changed. First we add a new property calleduserNamewith typestringin ./src/nameEdit.tsx. This one holds the last accepted value foruserName.
interface Props {
+ userName : string;
editingUserName : string;
onEditingNameUpdated : (newEditingName : string) => any;
onNameUpdateRequest : () => void;
}- We add to disabled an additional condition an to check if the value of
editingUserNamename has changed. Replace again only the input tag in ./src/nameEdit.tsx with the following code:
<button
className="btn btn-default"
onClick={props.onNameUpdateRequest}
- disabled={props.editingUserName === ''}
+ disabled={!props.editingUserName || props.userName === props.editingUserName}
>Change</button>- Now we have to feed this property from the parent control. Add
userName={this.state.userName}to the NameEditComponent in ./src/app.tsx. TheNameEditComponentshould be like:
public render() {
return (
<React.Fragment>
<HelloComponent userName={this.state.userName}/>
<NameEditComponent
++ userName={this.state.userName}
editingUserName={this.state.editingUserName}
onEditingNameUpdated={this.updateEditingName}
onNameUpdateRequest={this.setUsernameState} />
</React.Fragment>
);
}- Let's give a try
npm start
As an excercise, how can we get this in a more generic way? We could have a generic property called disable that could be true or false.
To do this, we modify ./src/app.tsx adding the variable disable to the <NameEditComponent> component. This variable is Boolean, so you need conditions to evaluate it.
public render() {
return (
<>
<HelloComponent userName={this.state.userName} />
<NameEditComponent
++ disable={!this.state.userName || this.state.userName === this.state.defaultUserName}
userName={this.state.userName}
editingUserName={this.state.editingUserName}
onEditingNameUpdated={this.updateEditingName}
onNameUpdateRequest={this.setUsernameState} />
</>
);
}Within the component we define the props disable as Boolean, together with its conditions that will evaluate it.
interface Props {
++ disable: boolean;
userName : string;
editingUserName : string;
onEditingNameUpdated : (newEditingName : string) => void;
onNameUpdateRequest : () => void;
}
export const NameEditComponent = (props : Props) =>
<div>
<label>Update Name:</label>
<input value={props.editingUserName}
onChange={(e) : void => props.onEditingNameUpdated((e.target as HTMLInputElement).value)} />
<button
className="btn btn-default"
onClick={props.onNameUpdateRequest}
-- disabled={!props.editingUserName || props.userName === props.editingUserName}
++ disabled={props.disable}
>Change</button>
</div>