Wordpress Save and edit Js, pass input value from edit to save - javascript

i'm trying to get the value of my select, to change the color of my text.
I have and RichText where i can enter text, but i want to change the color of this text with select input.
There is my code :
on edit.js
export default function Edit({ attributes, setAttributes, className, props }) {
const MyRadioControl = () => {
const [ option, setOption ] = useState( 'a' );
return (
<RadioControl
label="User type"
help="The type of the current user"
selected={ option }
options={ [
{ label: 'Author', value: 'a' },
{ label: 'Editor', value: 'e' },
] }
onChange={ ( value ) => setOption( value ) }
/>
);
};
const blockProps = useBlockProps();
return (
<h2 {...blockProps}>
<RichText
tagName="p"
value={attributes.content}
className ={MyRadioControl()}
allowedFormats={["core/italic"]}
onChange={(content) => setAttributes({ content })}
placeholder={__("Veuillez écrire du texte")}
/>
</h2>
);
}
I dont undertand how i can pass the select value , to my className.
Thanks!

Related

Typescript with React Hook Form and React-select Multiple selected value not submitted by the form

I am using react hook form and react select with typescript . Its works fine for single selected value. But when I choose isMulti for multiple selected value , I am unable to get the value from the submitted form .
Here is the code
interface ITopic {
value: string;
label: string;
}
...........
const topicOptions : ITopic[] = [
{ value: 'javascript', label: 'JAVASCRIPT' },
{ value: 'php', label: 'PHP' },
{ value: 'python', label: 'PYTHON' },
{ value: 'java', label:'JAVA' },
{ value: 'C#', label: 'C#' }
]
type TopicType = { label: string, value: string }
const [selectedTopic, setSelectedTopic] = useState<readonly ITopic[]>([]);
..........
<Controller
control={control}
render={({ field: { onChange, value, name, ref } }) =>{
const handleSelectionChange = (topicOptions: readonly SelectOptionType[]) => {
setSelectedTopic(topicOptions)
console.log(selectedTopic)
}
return (
<Select
isMulti
name={name}
value={selectedTopic}
options={topicOptions}
onChange={handleSelectionChange}
/>
)}}
name="topics"
/>
I am getting empty topics value. Need Help. Thank you.
First, if you are using react-hook-form to manage your form, you shouldn't in addition have useState for your variable.
What you want to do instead is to use onChange from the Controller's render method.
For instance, my multi select code is (assuming topicOptions is an array of TopicType: { label:string; value:string })
<Controller
control={control}
name="topics"
render={({ field: { onChange, value } }) => (
<Select
isMulti
name="topics"
options={topicOptions}
value={topicOptions.filter((el) => value?.includes(el.value))}
onChange={(option: TopicType[] | null) => {
if (option === null) {
onChange(null);
return;
}
onChange(option.map((el) => el.value));
}}
/>
)}
/>

Getting content of currently active Text component wrapped inside popover of antd

I am using antd components for my react app. I have a Text component wrapped inside of Popover component. Now in my case this Popover is applied to one particular column of table, i.e. every row-element in that column has a Popover component rendered for it upon mouse hovering.
title: "Name",
dataIndex: "name",
key: "name-key",
sortType: "string",
sortDirections: ["descend", "ascend"],
sorter: (a, b) => a.name.length - b.name.length,
render: (text, record) => (
<Popover>
<Text onMouseOver={handleOnMouseOverCommitId}> {name} </Text>
</Popover>
)
I want to get hold of the row-element's value, the one contained by the above Text component whenever I hover over it. In this case the value denoted by {name} above.
I tried getting it with e.target.value via onMouseOver event, but it returned undefined.
I think I get the reason behind it, because the event.target returns an html node of type <span>.
With a normal div element e.target.value has worked in the past for me. But doing the same thing with a predefined component like antd's Text seems a bit trickier.
Just to elaborate, the Popover has two buttons and based on which button user clicks, I need to render some other components, something like an overlay component.
But in order to do that I would also need to get hold of the text value which originally triggered the Popover.
Below is the code(most of the things removed for preciseness).
record.name is what I ultimately need to capture.
<Popover
content={
<>
<Space>
<Button onClick={showSomeOverlayPaneForName}>
{"View Details for record.name"}
</Button>
<Button href={"https://abc.xyz.com/" + record.role}>
{"View Role Details"}
</Button>
</Space>
</>
}
trigger={"hover"}
>
<Text style={{"color": blue.primary}} copyable={true} onMouseOver={handleOnMouseOverName}>{record.name}</Text>
</Popover>
The handleOnMouseOverName function(which doesn't work anyway) :
const handleOnMouseOverName = (e) => {
//console.log("e.target.value :--- ", e.target.value);
setCurrentActiveName(e.target.value)
}
And once my currentActiveName variable is set(via useState), I use that value inside my function showSomeOverlayPaneForName
const showSomeOverlayPaneForName = (e) => {
axios
.get(
`some-url`,
{
params: {name: currentActiveName}
}
)
.then((response) => {
setData(response.data);
}).catch(reason => {
//xyz
});
}
You need to pass on the record of the enclosing render function to the handleOnMouseOverName function.
Check the following example
import React from 'react';
import 'antd/dist/antd.css';
import './index.css';
import { Space, Table, Button, Popover } from 'antd';
const App = () => {
const data = [
{
key: '1',
name: 'John Brown',
address: 'New York No. 1 Lake Park',
role: 'admin',
},
{
key: '2',
name: 'Jim Green',
address: 'London No. 1 Lake Park',
role: 'user',
},
{
key: '3',
name: 'Joe Black',
address: 'Sidney No. 1 Lake Park',
role: 'manager',
},
];
const columns = [
{
title: 'Name',
dataIndex: 'name',
key: 'name',
render: (name, record) => {
const content = (
<>
<Space>
<Button
onClick={() => {
viewDetail(record);
}}
>
{'View Details for ' + record.name}
</Button>
<Button href={'https://abc.xyz.com/' + record.role}>
{'View Role Details'}
</Button>
</Space>
</>
);
return (
<>
<Popover content={content} title="Details">
<div
onMouseOver={() => {
handleOnMouseOverName(record);
}}
>
{name}
</div>
</Popover>
</>
);
},
},
{
title: 'Address',
dataIndex: 'address',
key: 'address',
},
];
const handleOnMouseOverName = (record) => {
console.log(record);
};
const viewDetail = (record) => {
console.log(record);
};
return <Table columns={columns} dataSource={data} />;
};
export default App;
Output:
I hope this helps.
From antd docs: https://ant.design/components/popover/#header
Apparently you're supposed to render the <Popover/> with a content={content}-prop
For example
const content = <div>Content to render under title</div>
const App = () => {
const value = "Text to hover";
return (
<Popover content={content} title="Title">
<Text>{value}</Text>
</Popover>
)
}

How to sync two dropdown lists with different display in React?

I have a list of countries, with key, value, text.
I would like to have two Dropdown (https://react.semantic-ui.com/modules/dropdown/) list, one shows the key, the other the text.
The goal is to allow to choose by key of by text (we can type in the dropdown); if I update one, the other is synchronized immediately.
How can I achieve this ?
<Dropdown
id='form-input-country'
label='Country'
placeholder='Select Country'
fluid
search
selection
options={countryISOOptions} // will show text
/>
<Dropdown
id='form-input-country'
label='Country'
placeholder='Select Country'
fluid
search
selection
options={countryISOOptions} // want to show key + want to sync in both direction
/>
I import countryISOOptions which looks like:
export const countryISOOptions = [
{key: 'AF', value: '4', text: 'Afghanistan'},
{key: 'AL', value: '8', text: 'Albania'},
{key: 'DZ', value: '12', text: 'Algeria'},
...
Maintain 2 option arrays. One for text and other for keys(derived from the first options array). Then maintain just one state and an onChange for both dropdowns and you will be fine.
See working copy of your code.
See code snippet:
import React, { useState } from "react";
import { Dropdown } from "semantic-ui-react";
import "./styles.css";
const countryISOOptions = [
{ key: "AF", value: "4", text: "Afghanistan" },
{ key: "AL", value: "8", text: "Albania" },
{ key: "DZ", value: "12", text: "Algeria" }
];
const countryKeys = countryISOOptions.map(({ key, value }) => ({
value,
text: key
}));
export default function App() {
const [text, setText] = useState("");
const onChangeTextDropdown = (e, d) => {
console.log("onChangeTextDropdown", e.target.value);
console.log("d", d);
setText(d.value);
};
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<Dropdown
id="form-input-countryz"
label="Country"
placeholder="Select Country - text"
value={text}
onChange={onChangeTextDropdown}
fluid
search
selection
options={countryISOOptions} // will show text
/>
<Dropdown
id="form-input-country"
label="Country"
placeholder="Select Country - key"
value={text}
onChange={onChangeTextDropdown}
fluid
search
selection
options={countryKeys} // want to show key + want to sync in both direction
/>
</div>
);
}
If you are using controlled version, then each Dropdown is a typical Inputthat supports two props called value and onChange. I'll use hook in the following example,
const [value1, setValue1] = setState('')
const [value2, setValue2] = setState('')
const onValue1Change = e => {
const value = e.target.value
setValue1(value)
if (value === 'key') setValue2('country')
}
return (
<div>
<Dropdown
value={value1}
onChange={onValue1Change}
...
/>
<Dropdown
value={value2}
...
/>
</div>
)

send the value as string when selecting the option

I am using react-select for autocomplete and option related field. When i select the option it passes whole that option object as {value: 'abc', label: 'ABC'} but i wanted only to pass the value as a string not the object. Thus, i used getOptionValue but it is not working as expected.
This is what I have done
<Field
name='status'
component={SearchableText}
placeholder="Search..."
options={status}
styles={styles}
getOptionLabel={option => option.label}
getOptionValue={option => option.value}
/>
I have used both getOptionLabel and getOptionValue but is still passing the selected option in object form instead of just the value as string.
Expected one
status: 'active'
Current behavior
status: { value: 'active', label: 'Active'}
I couldn't find getOptionValue in the docs for react-select, but you could always create an adapter around react-select. i.e. create your own Select component that uses react-select's Select component internally. After doing this it becomes possible to create your own getOptionValue. You can use this to make sure the value is a string.
import React from "react";
import Select from "react-select";
class MySelect extends React.Component {
getSelectValue() {
return this.props.options.find(
option => this.props.getOptionValue(option) === this.props.input.value
);
}
render() {
console.log("value", this.props.input.value);
return (
<Select
value={this.getSelectValue()}
onChange={option => {
this.props.input.onChange(this.props.getOptionValue(option));
}}
options={this.props.options}
/>
);
}
}
MySelect.defaultProps = {
getOptionValue: v => v
};
const MyForm = reduxForm({ form: "MyForm" })(
class extends React.PureComponent {
render() {
return (
<Field
name="myCoolSelect"
component={MySelect}
options={[
{ value: "chocolate", label: "Chocolate" },
{ value: "strawberry", label: "Strawberry" },
{ value: "vanilla", label: "Vanilla" }
]}
getOptionValue={option => option.value}
/>
);
}
}
);
The above is a basic example of how to get this working. You may want to pass other input or meta props to take advantage of other redux-form features. e.g. onBlur, onFocus, etc. You can see it in action here: https://codesandbox.io/s/6wykjnv32n

React-select does not show the selected value in the field

i have a react-select component which i define like this:
<Select
id="portf"
options={opts}
onChange={value => portfolioSelector(value)}
placeholder="Select Portfolio"
/>
with opts = [{label: any, value:1}, {label:Two, value:2}].
The values when selected are stored in the state via portfolioSelector function. The problem is that when i select a value it wasn't show in the select field. My main component is this:
const PortfolioSelector = ({
opts,
portfolioSelector
}) => {
if (opts) {
return (
<div className="portfolio select-box">
<label htmlFor="selectBox" className="select-box__label">
Portfolio
</label>
<div className="select-box__container">
<Select
id="portf"
options={opts}
onChange={value => portfolioSelector(value)}
placeholder="Select Portfolio"
/>
</div>
<div className="separator" />
</div>
);
}
return (
<div>Loading</div>
);
};
Do you know why?
This is an alternative solution that i used.
Demo: https://codesandbox.io/s/github/mkaya95/React-Select_Set_Value_Example
import React, { useState } from "react";
import Select from "react-select";
export default function App() {
const [selectedOption, setSelectedOption] = useState("none");
const options = [
{ value: "none", label: "Empty" },
{ value: "left", label: "Open Left" },
{ value: "right", label: "Open Right" },
{
value: "tilt,left",
label: "Tilf and Open Left"
},
{
value: "tilt,right",
label: "Tilf and Open Right"
}
];
const handleTypeSelect = e => {
setSelectedOption(e.value);
};
return (
<div>
<Select
options={options}
onChange={handleTypeSelect}
value={options.filter(function(option) {
return option.value === selectedOption;
})}
label="Single select"
/>
</div>
);
}
<Select
options={this.props.locale}
onChange={this.selectCountryCode}
value={{label : this.state.selectedCountryLabel}}
/>
The value property expects the shape Array.
The value is handled really bad, and it needs hacks like here, explained here.
Long story short; the value works differently. You'd expect
value={MY_VALUE}, but it works instead
value={{label: MY_VALUE}}.
First thing is you are created the wrong array, if label: any or Two is string you have to add double quote.
Look at this:
opts = [{label: "any", value:1}, {label:"Two", value:2}]
Second, You must remember the options in this case is opts is an array of object which have label and value, what the data you want to add to your state?
<Select
id="portf"
options={opts}
onChange={value => portfolioSelector(value.value /* or if you want to add label*/ value.label)}
placeholder="Select Portfolio"
/>
You can simply put the value property as Selected.label
value={selectedOption.label}
I fixed it.
You forgot add value property. Use this, check the working code:
const opts = [{ label: 'any', value: 1 }, { label: 'Two', value: 2 }];
const PortfolioSelector = ({ options }) => {
if (options) {
return (
<div className="portfolio select-box">
<label htmlFor="selectBox" className="select-box__label">
Portfolio
</label>
<div className="select-box__container">
<Select
id="portf"
options={options}
value={this.state.opts1}
onChange={value => this.setState({ opts1: value })}
placeholder="Select Portfolio" />
</div>
<div className="separator" />
</div>
);
}
return <div>Loading</div>;
};
and call your component
<PortfolioSelector options={opts} />
For any one who is facing problems with React-Select getting populated or React-select doesn't get selected value; try to give it a dynamic key attribute who changes every time your data changes (either options array or selected option), so it will re-render with new data.
this is my solution
Demo: https://codesandbox.io/s/prod-rgb-o5svh?file=/src/App.js
code:
import axios from 'axios'
import {useEffect, useState} from 'react'
import Select from 'react-select'
import "./styles.css";
export default function App() {
const [users, setUsers] = useState()
const [userId, setUserId] = useState()
useEffect(()=>{
const getUsers = async () => {
const {data} = await axios.get('https://jsonplaceholder.typicode.com/users')
setUsers(data)
}
getUsers()
},[])
const options = users && users.map(user =>{
return {label: user.name, value: user.id}
})
console.log(userId)
return (
<div className="App">
{users && (
<Select
placeholder='Select user...'
isSearchable
value={options.label}
options={options}
onChange={(option) => setUserId(option.value) }
/>
)}
</div>
)
}
Please provide lable and value object together like {label: ?, value: ?}
const selectedValue = options.find(x => x.value===value);
<Select
id="portf"
options={opts}
onChange={value => portfolioSelector(value)}
placeholder="Select Portfolio"
value={label : selectedValue.label, value: (value ? selectedValue.value : "")}
/>
opts = [{label: any, value:1}, {label:Two, value:2}]
value must be string.

Categories

Resources