reactJS hiding a <div> in the render leaves a lot of whitespace - reactjs

I have a reactJS application which renders from a map function. This is what some of the output looks like:
I am generating data for 3 beneficiaries and I am giving the user the option of deleting each beneficiary. The data is pulled from a database. Once the user has deleted whichever beneficiaries he/she wants to delete, the data will be written back to the database.
When a user clicks on the Delete this Beneficiary buttion, an onclick function is called. That function will set a flag (beneDeleteFlag) associated with that particular beneficiary. That data is written to the state with a setstate() so reactJS will re-render. When the render occurs, I set the classname of each section to either hide_div or show_div (which are classes in my .css file which set visibility to hidden or visible. This is the code that executes to render each beneficiary:
return idArray.map( item => (
<div>
<div className={item.visibility}>
<div className="beneficiary_background">
<div className="row">
<div className="col-3 text-left text_14">
<label>Name:</label>
</div>
<div className="col-9 text-left text_14">
<input type="text" id={item.thisName} value={item.beneName} maxLength="33"/>
</div>
</div>
<div className="row">
<div className="col-3 text-left text_14">
<label>SSN:</label>
</div>
<div className="col-9 text-left text_14">
<input type="text" id={item.thisMid} value={item.beneMid} maxLength="9"/>
</div>
</div>
<div className="row">
<div className="col-3 text-left text_14">
<label>Address 1:</label>
</div>
<div className="col-9 text-left text_14">
<input type="text" id={item.thisAddr1} value={item.beneAddr1} maxLength="20"/>
</div>
</div>
<div className="row">
<div className="col-3 text-left text_14">
<label>Address 2:</label>
</div>
<div className="col-9 text-left text_14">
<input type="text" id={item.thisAddr2} value={item.beneAddr2} maxLength="20"/>
</div>
</div>
<div className="row">
<div className="col-3 text-left text_14">
<label>Address 3:</label>
</div>
<div className="col-9 text-left text_14">
<input type="text" id={item.thisAddr3} value={item.beneAddr3} maxLength="20"/>
</div>
</div>
<div className="row">
<div className="col-3 text-left text_14">
<label>City</label>
</div>
<div className="col-9 text-left text_14">
<input type="text" id={item.thisCity} value={item.beneCity} maxLength="20"/>
</div>
</div>
<div className="row">
<div className="col-3 text-left text_14">
<label>State</label>
</div>
<div className="col-9 text-left text_14">
<input type="text" id={item.thisState} value={item.beneState} maxLength="2"/>
</div>
</div>
<div className="row">
<div className="col-3 text-left text_14">
<label>Zip Code</label>
</div>
<div className="col-9 text-left text_14">
<input type="text" id={item.thisZip} value={item.beneZip} maxLength="5"/>
</div>
</div>
<div className="row">
<div className="col-3 text-left text_14">
<label id="lblName">Spouse</label>
</div>
{this.renderSpouse(item.thisSpouse, item.beneSpouse)}
</div>
<div className="row">
<div className="col-3 text-left text_14">
<label id="lblName">Primary</label>
</div>
{this.renderPrimary(item.thisPorS, item.benePorS)}
</div>
<div className="row">
<div className="col-3 text-left text_14">
<label id="lblName">Percent</label>
</div>
<div className="col-9 text-left text_14">
<input type="text" id={item.thisPct} value={item.benePct} maxLength="3"/>
</div>
</div>
<div className="spacer">
</div>
<div className="row">
{this.renderDeleteButton(item.thisDelete)}
</div>
<div className="spacer">
</div>
</div>
</div>
<div className="spacer">
</div>
</div>
))
At the top of the render, there is a line of code that reads
<div className={item.visibility}>
{item.visibility} will contain hide_div for any beneficiary that the user elects to delete.
My issue is that when the delete the beneficiary button is clicked (I clicked on the button for the second beneficiary), and the {item.visibility} gets populated with hide_div, this is what gets rendered:
As you can see, the render occurs, but it just hides the . I though with bootstrap, the next would float up and not leave any whitespace between the two 's that are visible.
Any suggestions?

Try using reduce over map so you can selectively render your items instead of hiding the ones you don't want to see.
Something along the lines of:
return idArray.reduce( (all, item, idx) => {
if (item.visibility !== 'hide_div') {
all.push(
<div key={idx}>
<div className="beneficiary_background">
...
</div>
</div>
)
}
return all
}, [])
You won't need to set className for hidden items anymore

if you're using visibility: hidden, it will indeed leave the space there. Visibility Hidden leaves the space that should be occupied by the content hidden if it was visible. If you want no space left at all, use display: none instead. It will act the same way but without space left for the element.

you can filter the data which have been marked as deleted using filter function in javascript:
const array = [{beneDeleteFlag: true, data: 'data 1'}, {beneDeleteFlag: false, data: 'data 2'}, {beneDeleteFlag: false, data: 'data 3'}, {beneDeleteFlag: true, data: 'data 4'}]
const newArray = array.filter((item) => item.beneDeleteFlag !== true)
console.log(newArray)
and the reason why you still got the empty space in your UI, it's because you're using visibility: 'hidden' in your CSS, you should use display: 'none' instead.

Related

Bootstrap 5 - Change FORM width on mobile

I want a Form to display at 100% width on the desktop and 75% width on mobile.
Is there a way to do that using w-100 and w-75 or does that have to be accomplished with a media query? Also, the media query I'm using has no effect so I'm doing something wrong but I can't figure out what.
<style>
/* Portrait phones and smaller */
#media (min-width: 768px) {
.formwidth: {
{
width: 75%;
}
}
</style>
<script src="https://cdn.jsdelivr.net/npm/bootstrap#5.0.2/dist/js/bootstrap.bundle.min.js"></script>
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.0.2/dist/css/bootstrap.min.css" rel="stylesheet"/>
<div class="row align-items-center">
<div class="col-md-6 mx-auto d-block d-flex justify-content-center"> <img alt="Student Dashboard Login" src="https://efit.health/images/running-guy.svg" width="90%" class="mb-4" role="presentation" /></div>
<div class="col-md-6 col-sm-12 d-flex justify-content-center">
<form METHOD="post" ACTION="success.php" aria-label="Sign in to Student Dashboard" id="signin" class="formwidth">
<div role="group" aria-labelledby="contact-label">
<div class="form-group text-left mb-3 form-floating">
<input type="text" id="username" class="form-control" placeholder="Enter Username" name="username" aria-required="true" aria-label="Enter Username" required autofocus>
<label for="username" class="form-label">Username</label>
</div>
</div>
<div class="d-grid gap-2 mx-auto">
<button type="submit" class="btn btn-outline-primary btn-lg btn-responsive" value="Sign In">Sign In</button>
</div>
</form>
</div>
</div>
This can be done with the responsive .col-* classes and .w-100 on the form.
Remember BS uses "mobile first" ideology. You want to start with .col-8 75% on smallest screens and then .col-md-6 for half the row on medium and larger. Also you should have .justify-content-center on the parent .row:
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" />
<div class="row justify-content-center">
<div class="col-md-6 mx-auto d-block d-flex"> <img alt="Student Dashboard Login" src="https://efit.health/images/running-guy.svg" width="90%" class="mb-4" role="presentation" /></div>
<div class="col-8 col-md-6 d-flex ">
<form METHOD="post" ACTION="success.php" aria-label="Sign in to Student Dashboard" id="signin" class="w-100">
<div role="group" aria-labelledby="contact-label">
<div class="form-group text-left mb-3 form-floating">
<input type="text" id="username" class="form-control" placeholder="Enter Username" name="username" aria-required="true" aria-label="Enter Username" required autofocus>
<label for="username" class="form-label">Username</label>
</div>
</div>
<div class="d-grid gap-2 mx-auto">
<button type="submit" class="btn btn-outline-primary btn-lg btn-responsive" value="Sign In">Sign In</button>
</div>
</form>
</div>
</div>

How to customize input field length in AngularJS?

I have 4 input fields and type of each field is number. I have implemented it as follows
<div class="row ml-3 mr-3 mt-3">
<div class="column mr-3">
<label class="col-form-label">
Available Amount : <br/><input type="number"
class="mr-3"
[(ngModel)]="selectedItemAvailability"
[disabled]="true">
</label>
</div>
<div class="column ml-5">
<label class="col-form-label">
Enter Quantity : <br/><input type="number"
[min]="1"
[max]="selectedItemAvailability"
[(ngModel)]="selectedItemQuantity">
</label>
</div>
</div>
<div class="row ml-3 mr-3 mt-3">
<div class="column mr-3">
<label class="col-form-label">
Price : <br/><input type="number"
[min]="0"
class="mr-3"
[(ngModel)]="selectedItemPrice">
</label>
</div>
<div class="column ml-5">
<label class="col-form-label">
Item Discount : <br/><input type="number"
[min]="0"
[max]="100"
class="mr-3"
[(ngModel)]="selectedItemDiscount">
</label>
</div>
</div>
Once the program is executed, it gives me the interface as below,
When I use input type as text, it gives the expected output.
I want to make all the input fields same in length while using the input type as number. How can I achieve this?
Expected Output:
It seems your code works perfect. Please check stackblitz for the detail:
https://stackblitz.com/edit/angular-ivy-b7xnya?file=src/app/app.component.html
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.css" rel="stylesheet"/>
<div class="row ml-3 mr-3 mt-3">
<div class="column mr-3">
<label class="col-form-label">
Available Amount : <br /><input type="number" class="mr-3">
</label>
</div>
<div class="column ml-5">
<label class="col-form-label">
Enter Quantity : <br /><input type="number">
</label>
</div>
</div>
<div class="row ml-3 mr-3 mt-3">
<div class="column mr-3">
<label class="col-form-label">
Price : <br /><input type="number" [min]="0" class="mr-3">
</label>
</div>
<div class="column ml-5">
<label class="col-form-label">
Item Discount : <br /><input type="number" class="mr-3">
</label>
</div>
</div>

How to use colons in const

New to react and I am trying to use a colon like so (within the return of ProfilePage.js):
<a class="uk-text">{user.attributes.custom:company_name}</a>
but its giving me this error:
Parsing error: Unexpected token, expected "}"
I am getting attributes from an AWS Cognito User Pool and I can successfully see the returned object if I log it to the console like so:
Object >
custom:company_name: "apple"
custom:department: "dept"
custom:job_title: "title"
email: "email#me.com"
email_verified: false
family_name: "user"
given_name: "test"
locale: "location"
phone_number: "+18702831861"
phone_number_verified: false
sub: "guid"
I can get the family_name without issue:
<a class="uk-text">{user.attributes.family_name}</a>
but anytime I try the custom attributes with its colon, it throws the error.
Full ProfilePage.js code:
import React from "react";
import { API, graphqlOperation } from 'aws-amplify';
class ProfilePage extends React.Component {
state = {
};
componentDidMount() {
if (this.props.user) {
}
}
render() {
const { user } = this.props;
console.log(user.attributes)
const emailVerified = this.props.user.attributes.email_verified
const company_name = user.attributes.custom:company_name; // ERROR occurs here
return (
<>
<div class="container">
<div class="uk-margin-medium-top">
<ul class="uk-flex-center uk-tab">
<li class="uk-active"><a>Profile Summary</a></li>
</ul>
</div>
{/* Cards */}
<div class="uk-section">
<div class="uk-child-width-1-3#m uk-grid-small uk-grid-match uk-grid">
<div>
<div class="uk-card uk-card-default uk-card-body">
<h3 class="uk-card-title">User</h3>
<p>
{/* Form */}
<form class="uk-form-stacked">
<div class="uk-margin">
<label class="uk-form-label" for="form-stacked-text">User ID</label>
<div class="uk-form-controls">
<a class="uk-text-muted uk-link-reset">{user.attributes.sub}</a>
</div>
</div>
<div class="uk-margin">
<label class="uk-form-label" for="form-stacked-text">First Name</label>
<div class="uk-form-controls">
<a class="uk-text">{user.attributes.given_name}</a>
</div>
</div>
<div class="uk-margin">
<label class="uk-form-label" for="form-stacked-text">Last Name</label>
<div class="uk-form-controls">
<a class="uk-text">{user.attributes.family_name}</a>
</div>
</div>
<div class="uk-margin">
<label class="uk-form-label" for="form-stacked-text">Email <a class="uk-label uk-text-link">{emailVerified}</a></label>
<div class="uk-form-controls">
<input class="uk-input" id="form-stacked-text" type="text" placeholder={user.attributes.email} />
</div>
</div>
</form>
</p>
</div>
</div>
<div>
<div class="uk-card uk-card-primary uk-card-body">
<h3 class="uk-card-title">Company</h3>
<p>
{/* Form */}
<form class="uk-form-stacked">
<div class="uk-margin">
<label class="uk-form-label" for="form-stacked-text">Name</label>
<div class="uk-form-controls">
<a class="uk-text">{company_name}</a>
</div>
</div>
<div class="uk-margin">
<label class="uk-form-label" for="form-stacked-text">Role</label>
<div class="uk-form-controls">
<input class="uk-input" id="form-stacked-text" type="text" placeholder="Some text..." />
</div>
</div>
<div class="uk-margin">
<label class="uk-form-label" for="form-stacked-text">Description</label>
<div class="uk-form-controls">
<input class="uk-input" id="form-stacked-text" type="text" placeholder="Some text..." />
</div>
</div>
</form>
</p>
</div>
</div>
<div>
<div class="uk-card uk-card-secondary uk-card-body">
<h3 class="uk-card-title">Security</h3>
<p>
{/* Form */}
<form class="uk-form-stacked">
<div class="uk-margin">
<label class="uk-form-label" for="form-stacked-text">Change Password</label>
<div class="uk-form-controls">
<input class="uk-input" id="form-stacked-text" type="text" placeholder="Some text..." />
</div>
</div>
<div class="uk-margin">
<label class="uk-form-label" for="form-stacked-text">Multi-Factor Authenication</label>
<div class="uk-form-controls">
<input class="uk-input" id="form-stacked-text" type="text" placeholder="Some text..." />
</div>
</div>
<div class="uk-margin">
<label class="uk-form-label" for="form-stacked-text">Delete Account</label>
<div class="uk-form-controls">
<button class="uk-button uk-button-primary">Delete Account Forever</button>
</div>
</div>
</form>
</p>
</div>
</div>
</div>
</div>
</div>
</>
)
}
}
export default ProfilePage;
I do not even know what this use is called {user.attributes.custom:company_name}, reference to a const? Can someone educate me on what that is named and how do I use a colon within one?
Regards
You can access object's properties with brackets as well.
<a class="uk-text">{user.attributes["custom:company_name"]}</a>
Since a colon isn't a valid character for variables, object properties (because it's used to set a value to some property), you have to define/get the value with wrapping the name with quotes.
Hope I got the problem correctly.

JSX Bootstrap unterminated

I'm using bootstrap with react, and the compiler is failing on grounds that there is unterminated JSX contents. I've been through it a dozen times, and whichever way the ternary results, I don't see any unclosed tags. I'm new to react, so I suppose something else must be wrong. To cut down on code, I've only included the return():
<div className="container-fluid">
<div className="row">
<div className="col-12">
<SearchBar />
</div>
</div>
{this.state.results ? (
<div className="row">
<div className="col-12">
<div className="row">
<div className="col-6 offset-md-3">
<div className="row">
<div className="col">
<InputRange
maxValue={this.state.maxPrice}
minValue={this.state.minPrice}
value={this.state.priceRange}
formatLabel={x => {
return `£${x}`;
}}
onChange={value => this.setState({ priceRange: value })}
/>
</div>
</div>
<div className="row">
<div className="col">
Selection: {visibleResults.length}
</div>
</div>
<div>
</div>
<div className="row">
<div className="col-6 offset-md-3">
{visibleResults.map((item, index) => (
<Link to={`/listing/${item.id}`}>
<SearchResult result={item} key={index} />
</Link>
))}
</div>
</div>
</div>
</div>
) : (
<div className="row">
<div className="col">
<h1>LOADING...</h1>
</div>
</div>
)}
</div>
)
You need to close the div here:
<div className="row">
<div className="col">
Selection: {visibleResults.length}
</div>
</div>
<div> // This should be </div>
</div>

React select not displaying on html

I have a div that should be displaying a dropdown menu that grabs the values from my database and display in a dropdown. The dropdown isnt displaying at all but when i inspect the page and dig through whats on there, the dropdown is there but i can't see it.
<div className="row">
<div className="col s12 infoLanguageTop">
<div className="card infoLanguageTop">
<div className="card-content">
<span className="card-title">Deck Name: </span>
<div className='container'>
<select value={this.state.decks} onChange={this.handleDeckChange}>
{this.state.decks.map(decks => (
<option value={decks.deckName} />
))}
</select>
</div>
<div>
I am writing in:
<Dropdown options={languageOptions} onChange={this._onSelect} placeholder="Select a language" />
</div>
<div>
I would like to translate to:
<Dropdown options={languageOptions} onChange={this._onSelect} placeholder="Select a language" />
</div>
</div>
</div>
</div>
</div>

Resources