react: CSS breaks using classList in IE and Edge - javascript

CSS and app breaks in Edge and Internet Explorer for the following code-
componentDidMount() {
const styles = require('./GettingStarted.scss');
document.getElementById('bodyTag').classList = '';
document.getElementById('bodyTag').classList.add(styles.GettingStartedContainerBody);
document.getElementById('content').classList.remove(styles.AppContainerBody);
document.getElementById('content').classList = '';
document.getElementById('content').classList.remove(styles.AppContainerBodyWithoutLogin);
}
componentWillReceiveProps(nextProps) {
if (!this.props.checked && nextProps.checked) {
let queryString = '';
const windowLocation = window.location.href;
const queryStringStartIndex = windowLocation.indexOf('?');
if (queryStringStartIndex > 0) {
queryString = windowLocation.substring(queryStringStartIndex,windowLocation.length);
}
if(nextProps.result[0].status === '0') {
browserHistory.push(config.BASE_URL + '/userdetail' + queryString);
} else if(nextProps.result[0].status === '1') {
browserHistory.push(config.BASE_URL + '/signuplogin' + queryString);
}
}
}
render() {
const { checking, checkingError, fields: {emailid}} = this.props;
const styles = require('./GettingStarted.scss');
const pmdLogo = require('../../../static/plexusmd-logo.png');
return (
<div className={styles.gettingStartedPage}>
<Helmet {...config.app.head} title="Getting Started | PlexusMD" />
<div className="gettingStartedForm margin-top-bottom-40">
<div className="headerLogoMenuContainer text-center margin-bottom-30">
<IndexLink className="brandlogo" to={config.BASE_URL + '/gettingstarted'} >
<img className="brand" src={pmdLogo} width="80" height="25" title={config.app.title} alt={config.app.title} />
</IndexLink>
</div>
<form className="form" onSubmit={this.handleSubmit} >
<h2 className="orange font22 text-left text-bold text-uppercase margin-top-0 margin-bottom-50 margin-left-right-20">Getting started</h2>
<div className="form-group">
<label htmlFor="password" className="control-label gray">What's your Email address?</label>
<div className="input-group">
<input type="text" id="emailid" name="emailid" ref="emailid" placeholder="Email address" value={this.props.emailid} className="form-control text-lowercase" {...emailid}/>
{!emailid.error && <span id="emailid" className="input-group-addon input-group-icon"><i className="icon ion-ios-checkmark-empty icon-size green"/></span>}
{ emailid.error && emailid.dirty && <div id="emailid" className="red smaller margin-0-auto">Enter a valid Email</div>}
</div>
</div>
<div className="form-group">
<div className="text-right">
{checkingError && <p className="loginError red text-left">{checkingError}</p>}
{!checking && <button className="btn btn-primary" onClick={this.handleSubmit.bind(this)} disabled={emailid.error}>NEXT
</button>}
{checking && <button className="btn btn-primary" disabled={checking}>WAIT</button>}
</div>
</div>
<div className="clear"></div>
</form>
</div>
<div className="clear"></div>
</div>
);
}
The background color is not updating in this page, as well as the input field is disabled i.e., cannot type into the field unless I remove the props in the <input> tag.
AppContainerBody and AppContainerBodyWithoutLogin css classes are inherited from app.scss. GettingStartedContainerBody classlist belongs to GettingStarted.scss
I am adding these classlists in almost every file in my React app. The app works fine in Chrome, Firefox and Safari but I get this error in console:
Unhandled promise rejection TypeError: Assignment to read-only properties is not allowed in strict mode
Link to the app and App.scss and GettingStarted.scss.
Versions:
React: 0.14.2
Edge: 40.15063.674.0

Move all require statements out of your functions to the top of your file.
So instead of calling const styles = require('./GettingStarted.scss'); in each functions you want to use your styles, only import it once.
Like:
require('./GettingStarted.scss');
// or
import './GettingStarted.scss';
classList cannot be changed directly. Use classList.add and classList.remove or change the attribute class via className = '' or .setAttribute( 'class', '' )
Also try to minimize DOM selections/code duplicates by saving a selection to a variable, e.g.:
const bodyTag = document.getElementById('bodyTag');
// further instructions for #bodyTag
const content = document.getElementById('content');
// further instruction for #content

Related

DOM not getting updated Vue

<li
v-for="(schema) in typeSchema"
:key="schema.id"
>
<div style="display:inline-block; width:100%;">
<div style="display:flex; justify-content:space-between">
<span>{{ schema.title }}</span>
<span v-if="schema.controller">
<MdsSwitch
:checked="schema.controller.value"
:label="schema.controller.title"
#change="toggleController(schema, $event)"
/>
</span>
</div>
<div style="display:flex;flex-flow:column;place-items:flex-start;align-items:flex-start;margin-top:10px;">
<component
:is="schema.type"
v-bind="schema"
:data="data"
:is-disabled="schema.isDisabled"
#input="updateData"
/>
</div>
</div>
</li>
# toggleController(schema, event) {
if (schema.controller) {
// this.typeSchema.map(x => x).in
schema.controller.value = event;
schema.isDisabled = !event;
schema = { ...schema };
// const index = this.typeSchema.findIndex((x) => x.id === schema.id);
// console.log(index);
// this.$set(schema, "isDisabled", !event);
// this.typeSchema.splice(index, 0, schema);
}
},
When toggleController is executed it should disable the associated component, it was working earlier and I'm not sure what change I made and it stopped working, unfortunately everything is on my local so cannot refer pervious versions.
I have tried $set, splice but no luck

HTML Form input value not updating in javascript function

I have a simple HTML form which has an event listener binded to it and when you click on the button inside the form that has a class of 'booking__form__counter--increase' this should increase the input field value by 1. It calls a javascript function named 'increaseCounter()' I declare a variable that points to this value but when i try to use the variable to increment it, it doesn't work. If i use the methods in the variable directly it works? I am missing something simple here but i cannot work out what.
let bookingForm = document.querySelector('.booking__form');
bookingForm.addEventListener('click', function (e) {
let target = e.target;
let inputCounterValue = target.parentElement.firstElementChild.value;
let inputMaxCounterValue = target.parentElement.firstElementChild.dataset.maxCount;
let showCounterValue = target.parentElement.firstElementChild.nextElementSibling.textContent;
if (target.classList.contains('booking__form__counter--increase')) {
increaseCounter();
}
function increaseCounter() {
if (inputCounterValue === inputMaxCounterValue) {
return;
} else {
//does not update
inputCounterValue++;
showCounterValue = inputCounterValue;
//this does update
target.parentElement.firstElementChild.value++;
target.parentElement.firstElementChild.nextElementSibling.textContent = target.parentElement.firstElementChild.value;
}
}
});
<form class="booking__form">
<div class="container">
<div class="booking__form__group">
<div class="booking__form__section booking__form__section--arrival">
<div class="booking__form__control">
<label for="arrival">Arrival Date</label>
<div class="booking__form__counter">
<span class="booking__form__counter--value">0</span>
<div class="booking__form__counter--button booking__form__counter--increase">
<svg class="fal fa-chevron-up"></svg>
</div>
<div class="booking__form__counter--button booking__form__counter--decrease">
<svg class="fal fa-chevron-down"></svg>
</div>
</div>
</div>
</div>
<div class="booking__form__section booking__form__section--duration">
<div class="booking__form__control">
<label for="arrival">Nights</label>
<div class="booking__form__counter">
<input type="hidden" name="duration" value="1" data-max-count="21">
<span class="booking__form__counter--value">1</span>
<div class="booking__form__counter--button booking__form__counter--increase">
<svg class="fal fa-chevron-up"></svg>
</div>
<div class="booking__form__counter--button booking__form__counter--decrease">
<svg class="fal fa-chevron-down"></svg>
</div>
</div>
</div>
</div>
<div class="booking__form__section booking__form__section--adults">
<div class="booking__form__control" id="booking--adults">
<label for="arrival">Adults</label>
<div class="booking__form__counter">
<input type="hidden" name="adults" value="1" data-max-count="8">
<span class="booking__form__counter--value">1</span>
<div class="booking__form__counter--button booking__form__counter--increase">
<svg class="fal fa-chevron-up"></svg>
</div>
<div class="booking__form__counter--button booking__form__counter--decrease">
<svg class="fal fa-chevron-down"></svg>
</div>
</div>
</div>
</div>
<div class="booking__form__section booking__form__section--children">
<div class="booking__form__control" id="booking--children">
<label for="arrival">Children</label>
<div class="booking__form__counter">
<input type="hidden" name="children" value="0" data-max-count="5">
<span class="booking__form__counter--value">0</span>
<div class="booking__form__counter--button booking__form__counter--increase">
<svg class="fal fa-chevron-up"></svg>
</div>
<div class="booking__form__counter--button booking__form__counter--decrease">
<svg class="fal fa-chevron-down"></svg>
</div>
</div>
</div>
</div>
</div>
</div>
</form>
UPDATED Javascript
I have had a play around and added my updated javascript below which now seems to be working ok. I removed the data attributes 'data-max-count' and just added in the 'max' attribute and changed the variable decelerations around.
let bookingForm = document.querySelector('.booking__form');
bookingForm.addEventListener('click', function (e) {
let target = e.target;
let input = target.parentElement.firstElementChild;
let displayValue = target.parentElement.firstElementChild.nextElementSibling;
if (target.classList.contains('booking__form__counter--increase')) {
increaseCounter();
} else if (target.classList.contains('booking__form__counter--decrease')) {
decreaseCounter();
}
function increaseCounter() {
if (input.value === input.max) {
return;
} else {
input.value++;
displayValue.textContent = input.value;
}
}
});
I re-wrote your js and it now works.
You had some issues with your selectors and the way you updated the values.
I associated the max-count with the hidden input you have there and read the data-max-count attribute value. If this is not present then the auto-increment doesn't work because I set the initial value of inputMaxCounterValue equal to 0.
Keep in mind that I only update what the user sees and not the input value.
let bookingForm = document.querySelector('.booking__form');
bookingForm.addEventListener('click', function (e) {
let target = e.target;
let parentElem = target.parentElement;
let inputCounterValue = 0;
let valueContainer = parentElem.querySelector('.booking__form__counter--value');
if (typeof valueContainer.textContent!=="undefined") {
inputCounterValue = parseInt(valueContainer.textContent,10);
}
if (target.classList.contains('booking__form__counter--increase')) {
increaseCounter(valueContainer);
}
function increaseCounter(element) {
let inputMaxCounterValue = 0;
let parentElem = target.parentElement;
if (typeof parentElem.querySelector('input')!=="undefined" && parentElem.querySelector('input')!==null) {
inputMaxCounterValue = parentElem.querySelector('input').getAttribute("data-max-count");
}
if (inputCounterValue === inputMaxCounterValue) {
return;
} else {
//does not update
inputCounterValue++;
showCounterValue = inputCounterValue;
//this does update
element.textContent = inputCounterValue;
}

How to add props function in jquery by using react

I'm hoping you encounter the same issue of mine. I have react code that need a jquery event like (click, change). here is my code.
export default class SamplePreviewComponent extends React.Component<Props, any> {
constructor(props) {
super(props);
}
componentDidMount() {
this.renderChoiceButton();
}
renderChoiceButton() {
$("input.st").on("click", function() {
let value = $(this).val();
this.props.addDependentSample(value);
});
}
render() {
const { sampleTree } = this.props;
return (
<div className="row pl-1 pr-1 pt-0 mb-1">
<div className="columns bg-black20 pt-1 pb-1 border-radius-sm">
<div className="mb-1">
<p className="subheader">
<strong>
<small>SAMPLE #1</small>
</strong>
</p>
{sampleTree.root.label.trim().length > 0 && <h4>{sampleTree.root.label}</h4>}
{sampleTree.root.subLabel &&
sampleTree.root.subLabel.trim().length > 0 && (
<span className="subheader">
<small>
<strong>{sampleTree.root.subLabel}</strong>
</small>
</span>
)}
</div>
<div>
<div
dangerouslySetInnerHTML={{ __html: sampleTree.root.generatedHtml }}
className="red"
/>
</div>
</div>
</div>
);
}
}
if you check my return value of my component. there is dangerouslySetInnerHTML added. The output is like this
<div>
<div class="fancy-checkbox fancy-hover small mb-0">
<input type="checkbox" class="st" id="_0" name="17[]" value="1">
<label for="_0">1</label>
</div>
<div class="fancy-checkbox fancy-hover small mb-0">
<input type="checkbox" class="qt" id="_1" name="17[]" value="2">
<label for="_1">2</label>
</div>
</div>
When the user click the checkbox. I'm going to add and event using a jquery
renderChoiceButton() {
$("input.st").on("click", function() {
let value = $(this).val();
this.props.addDependentSample(value);
});
}
I get an error Cannot read property 'addDependentSample' of undefined. Maybe, because it comes from the react props and the jquery cannot read it. How can I add event using jquery that will connect the function to react?
There are a few ways you can resolve this error - a simple approach would be to store a reference to your component instance (ie componentInstance as shown below), and then access the component's props through that instance, like so:
renderChoiceButton() {
// Store reference to component for access in click handler
const componentInstance = this;
$('input.st').on('click', function() {
let value = $(this).val();
// Access props for the component via componentInstance
componentInstance.props.addDependentSample(value);
});
}

Could not display not found information using conditional syntax inside jsx

I have a searching system where user search by typing the place. If the place does not match, it should show not found and if place matches, it should show the place detail. What I did is
code
render() {
var margin = { marginTop : '13em' };
if (this.state.place){
let location = _.map(this.state.place, (place,id) => {
return(
<Room key={id}
slug={place.slug}
place={place.place}
city={place.city}
gallery={place.gallery}
property={place.property}/>
)
console.log('location',location);
});
let gallery = _.map(this.state.place, (place,id) => {
console.log('place',place.gallery);
_.map(place.gallery, (image,id) => {
return(
<img src={image.image} class="img-fluid" />
)
});
});
let noLocation = () => {
return(
<div className="noroom">There is no room</div>
);
console.log('nolocation');
};
return(
<div className = "container">
<div className="content text-align-center">
<div className="row text-xs-center">
<div className="middle-text" style={margin}>
<h1 className="welcome"><span>Common Rental Space</span></h1>
<p className="appSubtitle">facilitates your search for rental space all over Nepal</p>
<button ref="test" className="btn how-it-works" onClick={this.handleClick}>Search Space</button>
</div>
</div>
</div>
<div id="mySearch" className="overlay" onKeyDown={this.handleKeyDown}>
<button className="btn closebtn" onClick={this.handleClick}>x</button>
<div className="overlay-content">
<SearchInput ref="searchInput" className="search-input" onChange={this.searchUpdated} />
<div className="container searchList">
{ this.state.place > 1 ? {location} : {noLocation} }
</div>
</div>
</div>
</div>
);
}
}
}
What might be the error? The syntax is { condition ? true : false }
When I do {this.state.place >1 ? { location } : {noLocation} } I get an error
app.js:1030 Uncaught Invariant Violation: findComponentRoot(..., .0.1.1.1.0.0): Unable to find element. This probably means the DOM was unexpectedly mutated (e.g., by the browser), usually due to forgetting a <tbody> when using tables, nesting tags like <form>, <p>, or <a> or using non-SVG elements in an <svg> parent. Try inspecting the child nodes of the element with React ID ``.
When I do this.state.place >1?{location}:{noLocation}i get this.state.place >1 ? result, and if place does not match the page shows this.state.place >1 ? :.
noLocation appears to be a method, but you aren't actually calling the method anywhere - so you are basically telling reaction to render the function itself, not the result of the method.
If it must be a method, try, noting the extra ():
{ this.state.place.length >=1 ? location : noLocation() }

How to pass string with no quotes as a parameter in function?

If my api takes the query as http://localhost:8000/api/v1/rental/?place__startswith=kathmandu then how can i do generic search in reactjs. What i tried is i passed the default parameter as search(query=kathmandu) so that the result of place named kathmandu will be listed by default and when user types place name that they want to search then it should display those places instead of kathmndu. But i am getting an error saying Uncaught ReferenceError: kathmandu is not defined. How can i resolve this problem?
componentWillMount(){
this.search();
}
search(query=kathmandu){
let url = 'http://localhost:8000/api/v1/rental/?place__startswith=query';
Request.get(url).then((response) => {
console.log('response',response.body.objects);
this.setState({
place:response.body.objects
});
});
}
searchUpdated(term){
console.log('term is',term);
this.search(term);
}
render() {
var margin = { marginTop : '13em' };
let location = _.map(this.state.place, (place) => {
return(
<div className="searchResult">
<li>{place.place}</li>
<li>{place.city}</li>
</div>
)
});
return(
<div className = "container">
<div className="content text-align-center">
<div className="row text-xs-center">
<div className="middle-text" style={margin}>
<h1 className="welcome"><span>Welcome </span></h1>
<button ref="test" className="btn how-it-works" onClick={this.handleClick}>Search Space</button>
</div>
</div>
</div>
<div id="mySearch" className="overlay" onKeyDown={this.handleKeyDown}>
<button className="btn closebtn" onClick={this.handleClick}>x</button>
<div className="overlay-content">
<SearchInput ref="searchInput" className="search-input" onChange={this.searchUpdated} />
<ul>{location}</ul>
</div>
</div>
</div>
);
}
}
I think what you're looking for is encodeURIComponent.
search( query='kathmandu' ){
And:
let url = 'http://localhost:8000/api/v1/rental/?place__startswith=' + encodeURIComponent(query);
NB as your query string actually does only contains letter, you don't need encodeURIComponent for that example, but you might need it in other cases.

Categories

Resources