Is there a possibility to set singe value on React rc-slider Range component? At present to do that I need to drag the second handle in front of the first one or the first one drag after the second one and this behavior is allowing user to drag the handle behind the rail if we are on the edge values
I would like to set this up like on the third image it would show from eg. 39 to 39. Here is my code
import React, { useState } from "react";
import Slider, { Range } from "rc-slider";
import "rc-slider/assets/index.css";
export const RangeSlider = ({
min,
max,
error,
displayUnit,
stereo,
onChange
}) => {
const [minVal, setMinVal] = useState(min);
const [maxVal, setMaxVal] = useState(max);
const props = {
onChange: value => {
if (stereo) {
setMinVal(value[0]);
setMaxVal(value[1]);
} else {
setMinVal(value);
setMaxVal(value);
}
onChange(value);
},
min: min,
max: max,
defaultValue: stereo ? [0, 100] : 0
};
return (
<>
{error && (
<span className="position-outside">
<i className="fas fa-exclamation-circle fa text-danger mt-2"></i>
</span>
)}
<div className="text-primary h6 mb-3">
<strong>
{stereo &&
`Od ${minVal}${
displayUnit ? " " + displayUnit : ""
} do ${maxVal}${displayUnit ? " " + displayUnit : ""}`}
{!stereo &&
`${minVal}${displayUnit ? " " + displayUnit : ""}`}
</strong>
</div>
{stereo ? <Range {...props} /> : <Slider {...props} />}
</>
);
};
I am aware that single range slider is for single values, although the client has requested this feature.
Thanks
Firstly my apologies for making a confusion with the title and a question, the title should be different, I have found the bug I thought it was rc-slider, however it was me translating the second rail to be contained within the track, I have explained everything in detail in this post styling rc-slider track to contain handles within itself therefore I am closing this one. Thanks
Related
Hey so I'm working on a project where I need to display different components when users click on a button. Can you see if there's anyway I can reactor the code to be cleaner? I'm using react/next.js for the frontend.
Setting up useState to control which component is viewed. Using Boolean array as input
const [views, setViews] = useState([true, false, false])
Displaying the buttons that users will click to select view
<nav className='flex flex-row justify-end'>
<button
type='button'
className={`mainBtn p-2 mr-2` + (views[0] ? ' active' : '')}
onClick={() => setViews([true, false, false])}
>Create New Order</button>
<button
type='button'
className={`mainBtn p-2 mr-2` + (views[1] ? ' active' : '')}
onClick={() => setViews([false, true, false]) }
>View orders</button>
<button
type='button'
className={`mainBtn p-2 mr-2` + (views[2] ? ' active' : '')}
onClick={() => setViews([false, false, true]) }
>Manage account</button>
<button
type='button'
className={`mainBtn p-2 mr-2`}
onClick={() => signOut() }
>Sign Out</button>
</nav>
Using conditional rendering to display the desired components
{views[0] && <DisplayCreateNewOrder id={session.user.customer.locationID}/>}
{views[1] && <DisplayPendingOrders id={session.user.customer.locationID}/>}
{views[2] && <DisplayAccount customer={session.user.customer}/>}
any feedback is much appreciated. Also, the last two code blocks are wrapped in a div element with some tailwinds classes.
Thanks
You can simplify the state as only one view is visible at a time, there is no need to store three boolean variables. Full example - Codesandbox.
Store views in an enum/constant -
const Views = Object.freeze({
Create: "Create",
View: "View",
Manage: "Manage"
});
State can simply be current active view, very simple -
const [view, setView] = useState(Views.View);
Buttons can be refactored into one reusable component -
const LinkButton = ({ text, isActive, onClick }) => {
return (
<button
type="button"
className={`mainBtn p-2 mr-2` + (isActive ? " active" : "")}
onClick={onClick}
>
{text}
</button>
);
};
Then used as
<LinkButton
text="View Orders"
isActive={view === Views.View}
onClick={() => setView(Views.View)}
/>
First, from your code it is evident that only one view can appear at any given time. This means that instead of holding 3 booleans, you can just hold the id/name of the view that is currently active:
const {CreateNewOrder, ViewOrders, ManageAccount} = {'create', 'view', 'account'};
const [activeView, setActiveView] = useState(CreateNewOrder);
Then you can use a function to make the conditional more readable:
const isViewActive = view => activeView === view;
And you would use it like this:
{isViewActive(ManageAccount) && <DisplayAccount id={session.user.customer}/>}
There's probably more consolidation you could do by having all three views accept customer instead of some accepting only the ID.
I am working now on Exchange rates component. I have following code:
<div class="list-block" v-for="(item, index) in cashData.isNoCross" :key="index + '_exchangeRateList'">
<q-item class="list-block__element">
<q-item-section class="list-block__section">
<div v-for="(pic, index) in item.currency" :key="index">
<img :src="() => getImgUrl(pic)" />
</div>
<span class="indent-left">{{ item.currency }}</span>
</q-item-section>
</q-item>
<q-item class="list-block__element">
<q-item-section class="list-block__section">
<span class="title title--blue">{{ item.buyPrice }}</span>
<div v-for="(pic, index) in item.buyStatus" :key="index">
<img :src="() => getImgUrl(pic)" />
</div>
</q-item-section>
</q-item>
</div>
Here I am trying to display different icons correctly. That is, when the currency increases, the arrow is up, while decreasing down. If it has not changed, then just the dot icon. And also I have flag icons that I also need to show.
methods: {
getImgUrl(pic) {
if (pic === "isUp") {
return require("../../statics/icons/currency-icons/arrow-" + pic + ".svg");
}
if (pic === "isDown") {
return require("../../statics/icons/currency-icons/arrow-" + pic + ".svg");
}
if (pic === 'unchanged') {
return require("../../statics/icons/currency-icons/arrow-" + pic + ".svg");
}
if (pic) {
return require("../../statics/icons/currency-icons/" + pic + ".svg");
}
}
enter code here
My problem is that it can not display images.And instead of one icon for each element, it shows me three and five. Please help, I will be grateful for any answer.
Calling functions to render parts of your template is never a good option and the way you're trying to do it with an inline, anonymous function is simply not going to work.
I would instead provide a data property with those arrow images referenced by pic key and use that in your :src attributes, falling back to the default.
For example
data: () => ({
arrows: {
isUp: require("../../statics/icons/currency-icons/arrow-isUp.svg"),
isDown: require("../../statics/icons/currency-icons/arrow-isDown.svg"),
unchanged: require("../../statics/icons/currency-icons/arrow-unchanged.svg")
},
// and any other data properties you already had
})
<img :src="arrows[pic] || require(`../../statics/icons/currency-icons/${pic}.svg`)" />
I want to make some pagination, but I don't know why my gatsby link is automatically adding the current address then adding the to={}.
Imagine it like this:
I want to go page2 from page1. So, I will use Link to={page1} and the link should be localhost:8000/page1 instead what I get is localhost:8000/page2/page1
Here is the actual code. In pagetemplate.js:
export default function Program({ pageContext, data }) {
const post = data.cockpitProgram
const { previous, next } = pageContext
{previous && (
<Link to={previous.title.slug} rel="prev"
// className={ navLinkPrev}
>
<div
// className={ navPrev}
>
<h3
style={{margin:0,
fontSize:"1em"}}
>
{previous.title.value}
</h3>
</div>
<div
// className={ navMobilePrev}
>
<FontAwesomeIcon icon="chevron-circle-left"></FontAwesomeIcon>
</div>
</Link>
)}
In gatsby-node.js:
const pages = res.data.allCockpitProgram.edges
pages.forEach(( post,index ) => {
createPage({
path: `/${post.node.title.slug}/`,
component: program,
context: {
slug: post.node.title.slug,
previous: index === 0 ? null : pages[index - 1].node,
next: index === (pages.length - 1) ? null : pages[index + 1].node,
},
});
})
If you don't set a slash (/) at the beginning, it takes the path as relative. In the example: Link to={page1} should be Link to={/page1}.
Your pageContext seems to work properly, you are fetching the previous and next page, however, you are not setting correctly the <Link>'s destination.
So, in the provided code use <Link to={`/${previous.title.slug}`} rel="prev">.
I have a functional component in my React app that makes an API call and gets back a response featuring two contact methods Phone Number and Email and displays them next to their respective icon.
Some responses may only have one or the other contact method or neither.
In the event that a response doesn't have a contact method listed I still want to display the icon and place '--' where the data would be.
Here's my first pass at the logic where I tried writing out a few quick ternary methods, but right now all that renders on each row is [object Object][object Object]
let renderContactDetails = methods.map(method => {
return (
<div>
{
method.contactMethodType === "M" ? `${<span><PhoneSvg /> {method.number}</span>}` : `${<span><PhoneSvg /> -- </span>}`
}
{
method.contactMethodType === "E" ? `${<span><AtSymbolSvg /> {method.emailAddress}</span>}` : `${<span><AtSymbolSvg /> -- </span>}`
}
</div>
);
});
Any suggestions?
You only need to define JavaScript inside template literals and let JSX convert the html tags for you like this:
let renderContactDetails = methods.map(method => {
const number = method.contactMethodType === "M" ? `${method.number}` : `--`;
const email = method.contactMethodType === "E" ? `${method.emailAddress}` : `--`;
return (
<div>
<span><PhoneSvg /> {number}</span>
<span><PhoneSvg /> {email}</span>
</div>
);
});
You mixed up template strings with jsx syntax. Just do:
let renderContactDetails = methods.map(method => {
return (
<div>
{
method.contactMethodType === "M" ? <span><PhoneSvg /> {method.number}</span> : <span><PhoneSvg /> -- </span>
}
{
method.contactMethodType === "E" ? <span><AtSymbolSvg /> {method.emailAddress}</span> : <span><AtSymbolSvg /> -- </span>
}
</div>
);
});
And then render it.
return (
{renderContactDetails}
)
You don't need to wrap everything in a string, that is making your components to call toString() method, turning into [object Object]. Try doing something like this:
let renderContactDetails = methods.map(method => {
return (
<div>
{
method.contactMethodType === "M" ?
<span><PhoneSvg /> {method.number}</span>} :
<span><PhoneSvg /> -- </span>
}
{
method.contactMethodType === "E" ?
<span><AtSymbolSvg /> {method.emailAddress}</span> :
<span><AtSymbolSvg /> -- </span>
}
</div>
);
});
when I type 1sport1 I see the results.
when I type 1sport12 I dont see any results.
so that type I need to show no dta found.
and on clear all it should clear the text box.
but the problem is this line console.log("resp.json()--->", resp.json().[[PromiseValue]]);
I thought when length is 0 I will show the no data found.
but I am getting this error./src/searchbar.js: Unexpected token (31:48)
I am commenting the below lines so that you can see output in the browser
// console.log("resp.json()--->", resp.json().[[PromiseValue]]);
// display: this.state.noData ? "" : "none"
can you tell me how to show no data found when there is no data coming from api.
providing my code snippet and sandbox below.
https://codesandbox.io/s/jovial-cdn-14o1w
getQuery = async (type = "", search_tag = "") => {
var url = "https://hn.algolia.com/api/v1/search?tags=";
const resp = await fetch(`${url}${type}&query=${search_tag}`);
// console.log("resp.json()--->", resp.json().[[PromiseValue]]);
return resp.json();
};
render() {
console.log("this.state.noData--->", this.state.noData);
return (
<div>
<input type="text" onChange={this.searchByKeyword} />
<p
style={
{
// display: this.state.noData ? "" : "none"
}
}
>
No data found
<p>clear all</p>
</p>
{/* <Scroll /> */}
</div>
);
You can achieve this using conditional rendering on JSX.
Change your code to following and it will work.
<SearchBar onFetch={this.onFetch} />
{this.state.data && this.state.data.length > 0 ?
this.state.data.map((item) => <div key={item.objectID}>{item.title}</div>) :
<p>no data</p>}
I forked the sandbox and is here