How can I get label from Picker onValueChange in react-native - javascript

I want to get the value of items(in RNPickerSelect).
ex1) if my items is uc, then I want to get the label("ucCollege") as this.state.text.
ex2) if this.state.main_cate is "portal", then I want to get the label of const nul.
Finally I want to print the label as text like last code line.
How can I do this?
const uc = [
{
label: "ucCollege",
value: "uc",
},
];
const isa = [
{
label: "isaCollege",
value: "isa",
},
];
const nul = [
{
label: "nulCollege",
value: "nul",
},
];
export default class URL extends Component {
constructor(props) {
super(props);
this.state = {
main_cate: undefined,
sub_cate: undefined,
text: undefined,
};
}
render() {
return (
<View>
...
<RNPickerSelect
placeholder={sub_placeholder}
items={
this.state.main_cate === "portal"
? nul
: this.state.main_cate === "uc"
? uc
: isa (Actually there is more, but i comfortably omit that)
}
onValueChange={(value, index) => {
this.setState({
sub_cate: value,
text: items[index].label, // this is the point !!!
});
}}
value={this.state.sub_cate}
//label={this.state.sub_cate}
/>
<Text>{this.state.text}</Text> // And I want to print text like this
</View>
);
}
}

instead of items, you can directly reference your uc array like this and the index will pick the label.
onValueChange={(value, index) => {
this.setState({
sub_cate: value,
text: uc[index].label, // this is the point !!!
});
}}
Complete Code:
const uc = [
{
label: "ucCollege",
value: "uc",
},
];
const isa = [
{
label: "isaCollege",
value: "isa",
},
];
const nul = [
{
label: "nulCollege",
value: "nul",
},
];
export default class URL extends Component {
constructor(props) {
super(props);
this.state = {
main_cate: undefined,
sub_cate: undefined,
text: undefined,
};
}
render() {
return (
<View>
...
<RNPickerSelect
placeholder={sub_placeholder}
items={
this.state.main_cate === "portal"
? nul
: this.state.main_cate === "uc"
? uc
: isa //(Actually there is more, but i comfortably omit that)
}
onValueChange={(value, index) => {
this.setState({
sub_cate: value,
// instead of items you can directly refference your uc array like this
text: uc[index].label, // this is the point !!!
});
}}
value={this.state.sub_cate}
//label={this.state.sub_cate}
/>
<Text>{this.state.text}</Text> // And I want to print text like this
</View>
);
}
I hope this will help you out!

Related

How to insert variable inside Menu tag - REACTJS

I have a .js file containing the code for a context menĂ¹ component:
const ContextMenuDialog = (props) => {
// my state declaration, other const, etc...
const build_ITEMS_ContextMenu = () => {
const A = [
{
key: "0",
label: "AA123BB",
disabled: true
},
{
key: "1",
label: "Show"
},
{
key: "2",
label: "Edit"
},
{
key: "3",
label: "Save"
}
];
return A;
};
return (
<div>
{loading ? (
"Loading"
) : (
<Menu
title="Menu right click"
style={{ top: 10, left: 10 }}
onClick={my_onClick_function}
items={ build_ITEMS_ContextMenu }
/>
)}
</div>
)
}
export default ContextMenuDialog;
Just consider that I cannot simply past the code of const A directly inside the "items" element; if I do it,the code works properly. In the real life I need to build the const A with a my algorithm.
This code doesn't work, the context menĂ¹ is not shown!
How can I solve this problem?
the problem is that you are not calling the function.
try this items={ build_ITEMS_ContextMenu() }

Problem with alert after adding new value to the array in React.js

During the React.js course I'm doing, I was tasked with making a simple fortune-teller app. Theoretically, everything works as planned, but I did the task differently than the tutor. Instead of a simple fortune-telling table, I've created an array of objects, each with its id and 'omen'. The problem arose when after adding a new 'omen' an alert should be displayed that gives the current content of 'omens' in state. Only the previous values appear, without the added value. I will be grateful for the hints. In the original design, this problem does not occur, although it is very similar.
class Draw extends React.Component {
state = {
index: "",
value: "",
omens: [
{ id: 1, omen: "Hard work pays off" },
{ id: 2, omen: "You will be rich" },
{ id: 3, omen: "Be kind to others" },
],
};
handleDrawOmen = () => {
const index = Math.floor(Math.random() * this.state.omens.length + 1);
this.setState({
index: index,
});
};
showOmen = () => {
let omens = this.state.omens;
omens = omens.filter((omen) => omen.id === this.state.index);
return omens.map((omen) => (
<h1 id={omen.id} key={omen.id}>
{omen.omen}
</h1>
));
};
handleInputChange = (e) => {
this.setState({
value: e.target.value,
});
};
handleAddOmen = () => {
if (this.state.value === "") {
return alert("Enter some omen!");
}
const omens = this.state.omens.concat({
id: this.state.omens.length + 1,
omen: this.state.value,
});
this.setState({
omens,
value: "",
});
console.log(this.state.omens);
alert(
`Omen added. Actual omens: ${this.state.omens.map(
(omen) => omen.omen
)}`
);
};
render() {
return (
<div>
<button onClick={this.handleDrawOmen}>Show omen</button>
<br />
<input
placeholder="Write your own omen..."
value={this.state.value}
onChange={this.handleInputChange}
/>
<button onClick={this.handleAddOmen}>Add omen</button>
{this.showOmen()}
</div>
);
}
}
ReactDOM.render(<Draw />, document.getElementById("root"));
The state object is immutable. So you need to create your new array and apply it afterwards:
const omens = [
...this.state.omens,
{
id: this.state.omens.length + 1,
omen: this.state.value,
}
]
also setState is async so you need to wait until it finished:
this.setState({
omens,
value: "",
}, () => {
alert(
`Omen added. Actual omens: ${this.state.omens.map(
(omen) => omen.omen
)}`
)
https://reactjs.org/docs/react-component.html#setstate

Using JsonSchemaForm on change to update field's content

I am trying to use JsonSchema-Form component but i ran into a problem while trying to create a form that, after choosing one of the options in the first dropdown a secondary dropdown should appear and give him the user a different set o options to choose depending on what he chose in the first dropdown trough an API call.
The thing is, after reading the documentation and some examples found here and here respectively i still don't know exactly how reference whatever i chose in the first option to affect the second dropdown. Here is an example of what i have right now:
Jsons information that are supposed to be shown in the first and second dropdowns trough api calls:
Groups: [
{id: 1,
name: Group1}
{id: 2,
name: Group2}
]
User: [User1.1,User1.2,User2.1,User2.2,User3.1,User3.2, ....]
If the user selects group one then i must use the following api call to get the user types, which gets me the the USER json.
Component That calls JSonChemaForm
render(){
return(
<JsonSchemaForm
schema={someSchema(GroupOptions)}
formData={this.state.formData}
onChange={{}}
uiSchema={someUiSchema()}
onError={() => {}}
showErrorList={false}
noHtml5Validate
liveValidate
>
)
}
SchemaFile content:
export const someSchema = GroupOptions => ({
type: 'object',
required: [
'groups', 'users',
],
properties: {
groups: {
title: 'Group',
enum: GroupOptions.map(i=> i.id),
enumNames: GroupOptions.map(n => n.name),
},
users: {
title: 'Type',
enum: [],
enumNames: [],
},
},
});
export const someUISchema = () => ({
groups: {
'ui:autofocus': true,
'ui:options': {
size: {
lg: 15,
},
},
},
types: {
'ui:options': {
size: {
lg: 15,
},
},
},
});
I am not really sure how to proceed with this and hwo to use the Onchange method to do what i want.
I find a solution for your problem.There is a similar demo that can solve it in react-jsonschema-form-layout.
1. define the LayoutField,this is part of the demo in react-jsonschema-form-layout.To make it easier for you,I post the code here.
Create the layoutField.js.:
import React from 'react'
import ObjectField from 'react-jsonschema-form/lib/components/fields/ObjectField'
import { retrieveSchema } from 'react-jsonschema-form/lib/utils'
import { Col } from 'react-bootstrap'
export default class GridField extends ObjectField {
state = { firstName: 'hasldf' }
render() {
const {
uiSchema,
errorSchema,
idSchema,
required,
disabled,
readonly,
onBlur,
formData
} = this.props
const { definitions, fields, formContext } = this.props.registry
const { SchemaField, TitleField, DescriptionField } = fields
const schema = retrieveSchema(this.props.schema, definitions)
const title = (schema.title === undefined) ? '' : schema.title
const layout = uiSchema['ui:layout']
return (
<fieldset>
{title ? <TitleField
id={`${idSchema.$id}__title`}
title={title}
required={required}
formContext={formContext}/> : null}
{schema.description ?
<DescriptionField
id={`${idSchema.$id}__description`}
description={schema.description}
formContext={formContext}/> : null}
{
layout.map((row, index) => {
return (
<div className="row" key={index}>
{
Object.keys(row).map((name, index) => {
const { doShow, ...rowProps } = row[name]
let style = {}
if (doShow && !doShow({ formData })) {
style = { display: 'none' }
}
if (schema.properties[name]) {
return (
<Col {...rowProps} key={index} style={style}>
<SchemaField
name={name}
required={this.isRequired(name)}
schema={schema.properties[name]}
uiSchema={uiSchema[name]}
errorSchema={errorSchema[name]}
idSchema={idSchema[name]}
formData={formData[name]}
onChange={this.onPropertyChange(name)}
onBlur={onBlur}
registry={this.props.registry}
disabled={disabled}
readonly={readonly}/>
</Col>
)
} else {
const { render, ...rowProps } = row[name]
let UIComponent = () => null
if (render) {
UIComponent = render
}
return (
<Col {...rowProps} key={index} style={style}>
<UIComponent
name={name}
formData={formData}
errorSchema={errorSchema}
uiSchema={uiSchema}
schema={schema}
registry={this.props.registry}
/>
</Col>
)
}
})
}
</div>
)
})
}</fieldset>
)
}
}
in the file, you can define doShow property to define whether to show another component.
Next.Define the isFilled function in JsonChemaForm
const isFilled = (fieldName) => ({ formData }) => (formData[fieldName] && formData[fieldName].length) ? true : false
Third,after you choose the first dropdown ,the second dropdown will show up
import LayoutField from './layoutField.js'
const fields={
layout: LayoutField
}
const uiSchema={
"ui:field": 'layout',
'ui:layout': [
{
groups: {
'ui:autofocus': true,
'ui:options': {
size: {
lg: 15,
},
},
}
},
{
users: {
'ui:options': {
size: {
lg: 15,
},
},
doShow: isFilled('groups')
}
}
]
}
...
render() {
return (
<div>
<Form
schema={schema}
uiSchema={uiSchema}
fields={fields}
/>
</div>
)
}

Mobx react form add fields on click depending on condition

I have a function that generates fields for a form like so:
export const makeFields: Function = (itemData: Object) => {
return [
{
// PROJECT DETAIL SECTION
name: 'chooseAccount',
label: 'Choose Account',
fields: [{
name: 'account',
label: 'Choose Trading Account',
rules: 'required',
...(itemData ? { value: itemData.trading_account ? itemData.trading_account.name : null } : null)
}]
},
{
name: 'projectDetails',
label: 'Project detail',
fields: [
{
name: 'projectCode',
label: 'Project code',
rules: 'required',
...(itemData ? { value: itemData.code } : null)
},
...
and the component that uses this function for the form fields:
...
export default class ProjectForm extends React.Component<*> {
props: TypeProps;
getMode = () => this.props.mode
componentDidMount() {
const projectDetailsStore: Object = this.props.projectDetailsStore;
this.getMode() === 'edit'
?
projectDetailsStore.loadProjectDetails(this.props.projectId)
:
projectDetailsStore.resetStore();
}
#computed get form(): Object {
const itemData: Object = (typeof this.props.itemData === 'undefined') ? {} : this.props.itemData;
const fields: Array<*> = makeFields(this.props.projectDetailsStore.details);
return this.getMode() === 'edit'
? projectEdit(fields, itemData)
: projectCreate(fields);
}
render(): React.Element<*> {
const t: Function = this.props.t;
const TAmodel: AutoCompleteData = new AutoCompleteData(autoCompleteTradingAccounts);
const Pmodel: AutoCompleteData = new AutoCompleteData(autoCompleteProject);
const projectDetailsStore: Object = this.props.projectDetailsStore;
this.form.add(
{
name: 'test'
}
)
console.log(this.form)
return (
<PageWrapper>
{projectDetailsStore.loadingProjectDetails
?
<Loader />
:
<FormWrapper form={this.form}>
<form>
<FormSection form={this.form} section="chooseAccount">
<InputLabel htmlFor="account">
{t('projectForm: Choose trading account')}
</InputLabel>
<ElectroTextField field={this.form.$('chooseAccount.account')} />
{/* <ElectroAutoComplete
field={this.form.$('chooseAccount.account')}
form={this.form}
props={{
model: TAmodel
}}
/> */}
</FormSection>
<FormSection form={this.form} section="projectDetails">
<ElectroTextField field={this.form.$('projectDetails.projectCode')} />
<ElectroTextField field={this.form.$('projectDetails.projectName')} />
...
I would like to add some fields to the form based on a condition. I have tried the following:
this.form.add(
{
name: 'test'
}
)
it doesn't throw an error but nothing happens.
The add method takes an object as per the docs (https://foxhound87.github.io/mobx-react-form/docs/api-reference/fields-methods.html). Ideally I would like a click event to fire the add method and add the newly created field.
this.form is neither a React state nor a MobX observable, so that nothing happens when you change its value.
To get it to work, you should create an observable form field that is initialized by makeFields, and use an action function to change its value, and then use observer to re-render.
If you are not quite familiar with mentioned above, read React & MobX official tutorials first.

Implementing pagination in React that displays 15 items per page from a JSON file

I am having issues on even trying to get started with doing pagination without the use of any packages. I am pulling data from a JSON file that contains about 30-32 quotes. I need 15 quotes per page to be displayed and have no idea how to even do that using React. So far what I have is all the quotes being displayed by default. I have three buttons, each filters through the JSON to provide quotes by the theme of the quote which is displayed by the button. This is how far I got:
class App extends Component {
constructor(props) {
super(props);
this.state ={
results: quotes,
search: ""
}
}
gameFilterClick = event => {
event.preventDefault();
const games = [];
for(let i = 0; i < quotes.length; i++){
if (quotes[i].theme === "games"){
games.push(quotes[i])
}
}
this.setState({results: games})
}
movieFilterClick = event => {
event.preventDefault();
console.log('blah!!')
const movies = [];
for(let i =0; i < quotes.length; i++){
if(quotes[i].theme === 'movies'){
movies.push(quotes[i])
}
}
this.setState({results: movies})
}
allButtonClick = event => {
this.setState({results: quotes})
}
quoteSearch = query => {
let search = quotes.map
}
render() {
return (
<div className="App">
<h1>Quotes</h1>
<Search />
<div id='buttons'>
Filters:
<button onClick={this.allButtonClick}>All Quotes</button>
<button onClick={this.gameFilterClick}>Games</button>
<button onClick={this.movieFilterClick}>Movies</button>
</div>
<div id='resultsDiv'>
<Results
results={this.state.results}
/>
</div>
</div>
);
}
}
export default App;
I would recommend using react-bootstrap for this. You'll need to install two packages (they use to come in one, but now pagination package is separated):
react-bootstrap-table-next
react-bootstrap-table2-paginator
So, let's install them:
npm i --save react-bootstrap-table-next
npm i react-bootstrap-table2-paginator
And here goes a simple example of implementation:
import BootstrapTable from 'react-bootstrap-table-next';
import paginationFactory from 'react-bootstrap-table2-paginator';
// Let's imagine this is your JSON data
const yourJsonData = [{id: 1, author: "David Goggins", quote: "Life goes on"},
{ id: 2, author: "Robert Green", quote: "yes it does"}]:
// Here we define your columns
const columns = [{
dataField: 'author',
text: 'AUTHOR'
}, {
dataField: 'quote',
text: 'QUOTE'
}];
// Give it an option to show all quotes
let allQuotes = Number(yourJsonData.length);
// Set all of the major pagination options. You can reduce them if you want less
const options = {
paginationSize: 15,
pageStartIndex: 0,
firstPageText: 'First',
prePageText: 'Back',
nextPageText: 'Next',
lastPageText: 'Last',
nextPageTitle: 'First page',
prePageTitle: 'Pre page',
firstPageTitle: 'Next page',
lastPageTitle: 'Last page',
sizePerPageList: [{
text: 'show 15', value: 15
}, {
text: 'show 30', value: 30
}, {
text: 'Show all', value: allQuotes
}]
};
... and then somewhere later in your code where you want to display the table with pagination you just insert this:
<BootstrapTable
keyField='rowNumber'
data={ yourJsonData }
columns={ columns }
pagination={ paginationFactory(options) } />
I hope this solves your problem.
I've simplified your filtering logic and added client side pagination. Check out this simple working example (i've set item per page to 3, you can add more data and change it to 15 const QUOTES_PER_PAGE = <number of quotes per page>;)
const QUOTES_PER_PAGE = 3;
const Quote = ({text}) => <li>{text}</li>;
const Pagination = ({pages, goTo}) => (
<div>
{pages.map((p, i) => (
<button key={i} onClick={goTo} value={i}>{i+1}</button>
))}
</div>
)
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
page: 0,
pagedQuoutes: this.divideQuoutesIntoPages(props.quotes)
};
}
divideQuoutesIntoPages = (quotes => {
const pagedQuotes = [];
[...Array(Math.ceil(quotes.length/QUOTES_PER_PAGE))].forEach((q, i) => {
pagedQuotes.push(quotes.slice(0 + QUOTES_PER_PAGE*i, QUOTES_PER_PAGE + QUOTES_PER_PAGE*i))
})
return pagedQuotes;
})
filterQuoutes = (evt) => {
const filterValue = evt.target.value;
const filteredQuoutes = this.props.quotes.filter(q => !filterValue || q.theme === filterValue);
this.setState({
pagedQuoutes: this.divideQuoutesIntoPages(filteredQuoutes)
})
}
goToPage = (evt) => {
this.setState({
page: evt.target.value
})
}
render() {
return (
<div>
<h1>Quotes</h1>
<div>
Filters:
<button onClick={this.filterQuoutes}>All Quotes</button>
<button onClick={this.filterQuoutes} value="games">Games</button>
<button onClick={this.filterQuoutes} value="movies">Movies</button>
</div>
{this.state.pagedQuoutes[this.state.page]
.map(q => (
<ul>
<Quote {...q} />
</ul>
))}
<Pagination pages={this.state.pagedQuoutes} goTo={this.goToPage} />
</div>
);
}
}
const exampleQuotes = [{
theme: 'games',
text: 'games q1'
}, {
theme: 'games',
text: 'games q2'
}, {
theme: 'games',
text: 'games q3'
}, {
theme: 'games',
text: 'games q4'
}, {
theme: 'games',
text: 'games q5'
}, {
theme: 'movies',
text: 'movies q1'
}, {
theme: 'movies',
text: 'movies q2'
}, {
theme: 'movies',
text: 'movies q3'
}]
ReactDOM.render(<App quotes={exampleQuotes} />, document.getElementById("el"))
<div id="el"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

Categories