Display React component only when attribute is not null - javascript

MyReactComponent returns a hyperlink and a message after looking up an API using the name value. However I would like to render this component (which includes making the API call) only when name is not empty. Would the below solve the purpose or should I approach this differently?
<dt hidden={null == name || '' === name.trim()}>
<MyReactComponent name={name || ' '} />
</dt>

Here is another way you can do this :
{(name && name.trim() !== '') &&
<MyReactComponent name={name} />
}
You can learn more here.

Instead of using hidden attribute, you can render your component with ternary operator:
{name ? <MyReactComponent name={name} /> : null}

Related

Conditional statements to show a different component React js

i want to create a function or a conditional statement you can say that can show different components based on "If the user have bought products" then show the products components otherwise show "just a simple text like browse or buy products."
<div>
<Bookscard />
</div>
so this is my component, inside the component the purchased products are being mapped. Can i get a conditional statement that can either show this component like ( if user.courses is greater than or equal to 1 then show the component otherwise show a text ) something like this
You can try this:
<div>
{ user.courses.length > 0 &&
<Bookscard />
}
{ user.courses.length > 0 ||
<NoResults />
}
</div>
Or you can keep consistency with && by:
<div>
{ user.courses.length > 0 &&
<Bookscard />
}
{ user.courses.length == 0 &&
<NoResults />
}
</div>
Adding up to #Antoine Baqain's answer, you could use ternary operator too, like this:
<div>
{ user?.courses?.length > 0 ? <Bookscard /> : <NoResults /> }
</div>

How do I make it mandatory to select at least two options using the React Multiselect component?

I created one form control using the React Multiselect component. In this control, I want the 'required' to be removed when at least two of the Multiselect fields are selected.Required does not appear when user selects even one. Required appears only when nothing is selected. How can I do that?
React JS
const changeSelected = (selectedList, selectedItem) => {
const values = selectedList.toString();
setInput({...input, value: values})
dispatch(saveAnswer('f3', formKey, values))
}
return (
<>
<p>{comboboxName}</p>
<Multiselect className='btn-group'
style={{background: "red"}}
isObject={false}
closeIcon="close"
options={options} // Options to display in the dropdown
selectedValues={input.value ? input.value.split(',') : []} // Preselected value to persist in dropdown
onSelect={changeSelected} // Function will trigger on select event
onRemove={changeSelected} // Function will trigger on remove event
placeholder=''
/>
<p></p>
<Form.Check>
<Form.Check.Input required
checked={input.value != null && input.value.length > 1}
style={{display:'none' }}
/>
<Form.Control.Feedback type="invalid" >Required</Form.Control.Feedback>
</Form.Check>
</>
)
I guess this would solve your problem:
<Form.Check.Input
required = {input.value.length < 2 ? true : false}
checked={input.value != null && input.value.length > 1}
style={{display:'none' }}
/>

How to implement validation/restriction in react-datepicker

I am trying to implement restriction or validation in a react-datepicker component. I am using redux-form for validation and normalization(to implement restriction)
https://redux-form.com/6.0.0-rc.1/examples/normalizing/
Question : I have observed that neither normalizing function nor validation functions of redux-form is called when we try to enter something in the field
although this value is not submitted when we submit the form but i need to show some validation error or restrict user from typing invalid characters.
I made a wrapper for the date picker component and used it in my form through redux field
my date picker component :-
return (
<div className={"render-date-picker "}>
<div className="input-error-wrapper">
{(input.value) ? <label> {placeholder} </label> : ''}
<DatePicker className="input form-flow" {...input}
placeholderText={placeholder}
selected={input.value ? moment(input.value) : null}
maxDate={maxDate || null}
minDate={minDate || null}
dateFormat={isTimePicker ? "LLL" : "DD/MM/YYYY"}
showYearDropdown
showMonthDropdown
disabledKeyboardNavigation
/>
{touched && error && <span className="error-msg">{t(error)}</span>}
<span className="bar" style={{ 'display': this.state.is_focus ? 'block' : 'none' }} ></span>
</div>
</div>
);
redux form field :-
<Field
name="date_of_birth"
type="text"
className="input form-flow extra-padding-datepicker"
component={RenderDatePicker}
maxDate={moment().subtract(18, "years")}
validate={[required, dateOfBirth]}
normalize={isValidDateFormat}
placeholder={t("DOB (DD/MM/YYYY)")}
/>
my normalizing function:-
export const isValidDateFormat = (value, previousValue) => {
if (value == null || !value.isValid()) {
return previousValue;
}
return value;
}
react-datepicker provides onChangeRaw property to get raw (typed) value inside the datePicker. In order to restrict or validate the datepicker input field we need the raw value which is not available on onChange event of the datepicker component.
for instance if we observe the onChange event :-
It returns a moment object.
In order to get raw value we use onChangeRaw
The raw value is obtained simply from e.target.value.
In my case I simply restrict the user from typing anything in the datepicker input field by a simple function:-
handleChangeRaw = (date) => {
let s=document.getElementById(date_picker_id)
s.value =moment(this.props.input.value).format("DD/MM/YYYY");
}
My datepicker component :-
<DatePicker
.....
disabledKeyboardNavigation
onChangeRaw={(e)=>this.handleChangeRaw(e)}
id={date_picker_id}
.....
/>
This solved my problem. Hope it is useful :)

JXS if else class doesn't work

{item.status}
<div className="{item.status !== '' ? 'hide' : ''} pull-right">Content</div>
Why above jsx has no effect? My item.status value is string. But in my DOM I can't see hide class been added.
This is because you have wrapped your ternary operator in " so it is treated as string. Try this instead:
{item.status}
<div class={"pull-right "+(item.status !== '' ? 'hide' : '')}>Content</div>
Beside what #rahul-pratap-singh said, consider using nice, tiny package called classnames - link here so you can use it like:
import classes from 'classnames';
// later on
<div className={classes({
"pull-right": true,
"hide": item.status !== '',
})} />
I think it leads to much cleaner code than joining string.
Or at least use es6 string interpolation - link here
// instead of
"pull-right "+(item.status !== '' ? 'hide' : '')
// with string interpolation
`pull-right ${item.status.length ? '' : 'hide'}`;

Passing JSX to components vs dangerouslySetInnerHTML

I've been working through react examples, and I've been hacking away building some components. Now I feel i'm running into a fundamental "Brain Fart", regarding component structure and nesting.
What I'm after:
Input component with Optional Labels and help text.
What I have right now: ( which does work )
Input.js
//...//
var MyInput = React.createClass( {
render: function() {
//...//
var helpText = null;
if( typeof this.props.helpText !== 'undefined' ){
helpText = <p className="help-block" > {this.props.helpText} </p>;
}
return (
<div className={ className }>
<MyLabel showLabel={ this.props.showLabel} htmlFor={ this.props.name }>
{ this.props.title }
</MyLabel>
<input
type={ this.props.type || 'text' }
name={ this.props.name }
onChange={ this.changeValue }
value={ this.getValue() }
checked={ this.props.type === 'checkbox' && this.getValue() ? 'checked' : null }
placeholder={ this.props.title }
/>
<span className='validation-error'>{ errorMessage }</span>
{helpText}
</div>
);
}
});
module.exports = MyInput;
LoginForm.js
//...//
var LoginForm = React.createClass({
// ... //
render: function() {
return (
<Form className=" col-sm-11 col-lg-10 block-center loginFrm" >
<div className="row">
<FrmInput value =""
name="username"
title="Username"
className="col-sm-5"
showLabel={false}
helpText= { <span> Help text with link </span>}
required />
<FrmInput value =""
type="password"
name="password"
title="Password"
className="col-sm-5"
showLabel={false}
required />
<button type="submit"
className="btn btn-default input-sm "
>
Sign In
</button>
</div>
<div className="row">
<div className="pull-right" >
<FrmCheckbox name="rememberMe"
title="Remember Me"
/>
</div>
</div>
</Form>
);
},
});
module.exports = LoginForm;
Making the label optional was easy. I use a BOOL showLabel property on the <MyInput/> component and pass that into the MyLabel component. showLabel is assumed TRUE, so the label is shown unless you set showLabel to false as seen above ( then <MyLabel/> just returns NULL ).
I first tried a similar method with a <help/> component to add the optional help text after the input inside <MyInput/>. Everything worked until I added a link inside the help text. Researching I found dangerouslySetInnerHTML as a means to pass HTML content into a component. While testing I also found the code above appears to work also, though I'm not exactly sold on why and how "good" this approach is.
In short it appears I'm just passing JSX objects into my component for rendering. inside <Form> (from LoginForm.js ) on the <FrmInput/> component there is a property named helpText set as follows
helpText= { <span> Help text with link </span> }
inside the <MyInput/> component I'm testing/listening for the helpText property and setting it to a variable when found (Again wrapping with JSX)
var helpText = null;
if( typeof this.props.helpText !== 'undefined' ){
helpText = <p className="help-block" > {this.props.helpText} </p>;
}
Then in the Render Method I have { helpText }
All in all it looks like I'm just passing javascript objects ( via JSX ) on through untill the final render method. I have not seen the above used in tutorials or documentation, so I'm just looking for a professional opinion.
Is the above "good" practice or how could this better be handled.
There's nothing 'wrong' with your approach. A few suggestions that can help stream line a bit.
You can shorten this block to a simple inline ternary:
var helpText = null;
if( typeof this.props.helpText !== 'undefined' ){
helpText = <p className="help-block" > {this.props.helpText} </p>;
}
You can remove the above and in your render replace {helpText} with:
{ this.props.helpText ? this.props.helpText : null }
In form input remove the inline helpText html and move to a variable using parens for the JSX.
const helpTextContent = ( <span> Help text with link </span> );
Then inline: helpText = { helpTextContent }
Lastly if you're using ES6 you can use the following syntax to make using props less cumbersome:
let { helpText, someOtherProp, anotherProp } = this.props;
Then you can just refer to helpText or someOtherProp directly without the this.prop every time.
Hope that helps!

Categories

Resources