aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar ks129 <[email protected]>2021-02-23 09:46:27 +0200
committerGravatar ks129 <[email protected]>2021-02-23 09:46:27 +0200
commitdfbd9eb719bda4a672884bb7d42c353fde75a5e6 (patch)
tree7d0ba7016a3dc6d41f74052c7db126a2adf37045
parentChange Redux store items from map to object (diff)
Use values from Redux in fieldsredux-hcaptcha
-rw-r--r--src/components/InputTypes/Checkbox.tsx18
-rw-r--r--src/components/InputTypes/Radio.tsx8
-rw-r--r--src/components/InputTypes/Range.tsx8
-rw-r--r--src/components/InputTypes/Select.tsx6
-rw-r--r--src/components/InputTypes/TextArea.tsx12
-rw-r--r--src/components/InputTypes/index.tsx8
-rw-r--r--src/components/Question.tsx43
7 files changed, 70 insertions, 33 deletions
diff --git a/src/components/InputTypes/Checkbox.tsx b/src/components/InputTypes/Checkbox.tsx
index 38b8ee8..9c633f0 100644
--- a/src/components/InputTypes/Checkbox.tsx
+++ b/src/components/InputTypes/Checkbox.tsx
@@ -3,13 +3,15 @@ import { jsx, css } from "@emotion/react";
import React, { ChangeEvent } from "react";
import colors from "../../colors";
import { multiSelectInput, hiddenInput } from "../../commonStyles";
-import {useSelector} from "react-redux";
-import {FormState} from "../../store/form/types";
+import { useSelector } from "react-redux";
+import { FormState } from "../../store/form/types";
+import { Question } from "../../api/question";
interface CheckboxProps {
index: number,
option: string,
- handler: (event: ChangeEvent<HTMLInputElement>) => void
+ handler: (event: ChangeEvent<HTMLInputElement>) => void,
+ question: Question
}
const generalStyles = css`
@@ -58,10 +60,16 @@ export default function Checkbox(props: CheckboxProps): JSX.Element {
const values = useSelector<FormState, FormState["values"]>(
state => state.values
);
+ let value = values[props.question.id];
+ if (typeof value !== "object" || !value) {
+ value = {};
+ }
+ const checked = value[`${("000" + props.index).slice(-4)}. ${props.option}`];
+
return (
<label css={[generalStyles, activeStyles]}>
- <label className="unselected" css={multiSelectInput}>
- <input type="checkbox" value={props.option} css={hiddenInput} name={`${("000" + props.index).slice(-4)}. ${props.option}`} onChange={props.handler} checked={!!values[`${("000" + props.index).slice(-4)}. ${props.option}`]}/>
+ <label className={checked ? "selected" : "unselected"} css={multiSelectInput}>
+ <input type="checkbox" value={props.option} css={hiddenInput} name={`${("000" + props.index).slice(-4)}. ${props.option}`} onChange={props.handler} checked={checked}/>
<span className="checkmark"/>
</label>
{props.option}<br/>
diff --git a/src/components/InputTypes/Radio.tsx b/src/components/InputTypes/Radio.tsx
index a857964..68c9519 100644
--- a/src/components/InputTypes/Radio.tsx
+++ b/src/components/InputTypes/Radio.tsx
@@ -3,6 +3,8 @@ import { jsx, css } from "@emotion/react";
import React, { ChangeEvent } from "react";
import colors from "../../colors";
import { multiSelectInput, hiddenInput } from "../../commonStyles";
+import { useSelector } from "react-redux";
+import { FormState } from "../../store/form/types";
interface RadioProps {
option: string,
@@ -30,9 +32,13 @@ const styles = css`
`;
export default function Radio(props: RadioProps): JSX.Element {
+ const values = useSelector<FormState, FormState["values"]>(
+ state => state.values
+ );
+ const value = values[props.question_id];
return (
<label css={styles}>
- <input type="radio" name={props.question_id} onChange={props.handler} css={hiddenInput} onBlur={props.onBlurHandler}/>
+ <input type="radio" name={props.question_id} onChange={props.handler} css={hiddenInput} onBlur={props.onBlurHandler} checked={value === props.option}/>
<div css={multiSelectInput}/>
{props.option}<br/>
</label>
diff --git a/src/components/InputTypes/Range.tsx b/src/components/InputTypes/Range.tsx
index 23cb3f6..8d37b8a 100644
--- a/src/components/InputTypes/Range.tsx
+++ b/src/components/InputTypes/Range.tsx
@@ -3,6 +3,8 @@ import { jsx, css } from "@emotion/react";
import React, { ChangeEvent } from "react";
import colors from "../../colors";
import { hiddenInput, multiSelectInput } from "../../commonStyles";
+import { useSelector } from "react-redux";
+import { FormState } from "../../store/form/types";
interface RangeProps {
question_id: string,
@@ -97,11 +99,15 @@ const sliderStyles = css`
`;
export default function Range(props: RangeProps): JSX.Element {
+ const values = useSelector<FormState, FormState["values"]>(
+ state => state.values
+ );
+ const value = values[props.question_id];
const range = props.options.map((option, index) => {
return (
<label css={[selectorStyles, css`width: 1rem`]} key={index}>
<span css={optionStyles}>{option}</span>
- <input type="radio" name={props.question_id} css={hiddenInput} onChange={props.handler} onBlur={props.onBlurHandler}/>
+ <input type="radio" name={props.question_id} css={hiddenInput} onChange={props.handler} onBlur={props.onBlurHandler} checked={value === option}/>
<div css={multiSelectInput}/>
</label>
);
diff --git a/src/components/InputTypes/Select.tsx b/src/components/InputTypes/Select.tsx
index c0f5425..82e0975 100644
--- a/src/components/InputTypes/Select.tsx
+++ b/src/components/InputTypes/Select.tsx
@@ -16,11 +16,11 @@ interface SelectProps {
}
interface SelectStateProps {
- values: Map<string, string | Map<string, boolean> | null>
+ values: { [key: string]: string | { [subKey: string]: boolean; } | null; }
}
interface SelectDispatchProps {
- setValue: (question: Question, value: string | Map<string, boolean> | null) => SetValueAction
+ setValue: (question: Question, value: string | { [key: string]: boolean } | null) => SetValueAction
}
const containerStyles = css`
@@ -191,7 +191,7 @@ class Select extends React.Component<SelectProps & SelectStateProps & SelectDisp
}
focusOption(): void {
- if (!this.props.values.get(this.props.question.id)) {
+ if (!(this.props.question.id in this.props.values) || !this.props.values[this.props.question.id]) {
this.props.setValue(this.props.question, "temporary");
this.props.onBlurHandler();
this.props.setValue(this.props.question, null);
diff --git a/src/components/InputTypes/TextArea.tsx b/src/components/InputTypes/TextArea.tsx
index 08424fb..a32094c 100644
--- a/src/components/InputTypes/TextArea.tsx
+++ b/src/components/InputTypes/TextArea.tsx
@@ -2,13 +2,17 @@
import { jsx, css } from "@emotion/react";
import React, { ChangeEvent } from "react";
import { invalidStyles, textInputs } from "../../commonStyles";
+import { useSelector } from "react-redux";
+import { FormState } from "../../store/form/types";
+import { Question } from "../../api/question";
interface TextAreaProps {
handler: (event: ChangeEvent<HTMLTextAreaElement>) => void,
onBlurHandler: () => void,
valid: boolean,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
- focus_ref: React.RefObject<any>
+ focus_ref: React.RefObject<any>,
+ question: Question
}
const styles = css`
@@ -21,9 +25,13 @@ const styles = css`
`;
export default function TextArea(props: TextAreaProps): JSX.Element {
+ const values = useSelector<FormState, FormState["values"]>(
+ state => state.values
+ );
+ const value = values[props.question.id];
return (
<div css={invalidStyles}>
- <textarea css={[textInputs, styles]} placeholder="Enter Text..." onChange={props.handler} onBlur={props.onBlurHandler} className={!props.valid ? "invalid-box" : ""} ref={props.focus_ref}/>
+ <textarea css={[textInputs, styles]} value={typeof value === "string" ? value : ""} placeholder="Enter Text..." onChange={props.handler} onBlur={props.onBlurHandler} className={!props.valid ? "invalid-box" : ""} ref={props.focus_ref}/>
</div>
);
}
diff --git a/src/components/InputTypes/index.tsx b/src/components/InputTypes/index.tsx
index ff02259..97fd790 100644
--- a/src/components/InputTypes/index.tsx
+++ b/src/components/InputTypes/index.tsx
@@ -37,11 +37,11 @@ export default function create_input(props: QuestionProp & QuestionStateProp & Q
/* eslint-disable react/react-in-jsx-scope */
switch (question.type) {
case QuestionType.TextArea:
- result = <TextArea handler={handler} valid={valid} onBlurHandler={onBlurHandler} focus_ref={focus_ref}/>;
+ result = <TextArea question={question} handler={handler} valid={valid} onBlurHandler={onBlurHandler} focus_ref={focus_ref}/>;
break;
case QuestionType.Checkbox:
- result = options.map((option, index) => <Checkbox index={index} option={option} handler={handler} key={index}/>);
+ result = options.map((option, index) => <Checkbox question={question} index={index} option={option} handler={handler} key={index}/>);
break;
case QuestionType.Radio:
@@ -53,7 +53,7 @@ export default function create_input(props: QuestionProp & QuestionStateProp & Q
break;
case QuestionType.ShortText:
- result = <ShortText handler={handler} onBlurHandler={onBlurHandler} valid={valid} focus_ref={focus_ref} question={question}/>;
+ result = <ShortText key={props.question.id} handler={handler} onBlurHandler={onBlurHandler} valid={valid} focus_ref={focus_ref} question={question}/>;
break;
case QuestionType.Range:
@@ -66,7 +66,7 @@ export default function create_input(props: QuestionProp & QuestionStateProp & Q
break;
default:
- result = <TextArea handler={handler} valid={valid} onBlurHandler={onBlurHandler} focus_ref={focus_ref}/>;
+ result = <TextArea question={question} handler={handler} valid={valid} onBlurHandler={onBlurHandler} focus_ref={focus_ref}/>;
}
/* eslint-enable react/react-in-jsx-scope */
diff --git a/src/components/Question.tsx b/src/components/Question.tsx
index 7212a2d..74ee86f 100644
--- a/src/components/Question.tsx
+++ b/src/components/Question.tsx
@@ -1,14 +1,14 @@
/** @jsx jsx */
import { jsx, css } from "@emotion/react";
-import React, { ChangeEvent } from "react";
-import { connect } from "react-redux";
+import React, {ChangeEvent} from "react";
+import {connect} from "react-redux";
-import { Question, QuestionType } from "../api/question";
-import { selectable } from "../commonStyles";
+import {Question, QuestionType} from "../api/question";
+import {selectable} from "../commonStyles";
import create_input from "./InputTypes";
import ErrorMessage from "./ErrorMessage";
-import { FormState } from "../store/form/types";
-import { setError, SetErrorAction, setValid, SetValidAction, setValue, SetValueAction } from "../store/form/actions";
+import {FormState} from "../store/form/types";
+import {setError, SetErrorAction, setValid, SetValidAction, setValue, SetValueAction} from "../store/form/actions";
const skip_normal_state: Array<QuestionType> = [
QuestionType.Radio,
@@ -47,10 +47,14 @@ export class RenderedQuestion extends React.Component<QuestionProp & QuestionSta
}
this.blurHandler = this.blurHandler.bind(this);
- props.setValid(props.question, true);
- props.setError(props.question, "");
+ if (!(props.question.id in props.valid)) {
+ props.setValid(props.question, true);
+ }
+ if (!(props.question.id in props.errors)) {
+ props.setError(props.question, "");
+ }
- if (!skip_normal_state.includes(props.question.type)) {
+ if (!skip_normal_state.includes(props.question.type) && !(props.question.id in props.values)) {
props.setValue(props.question, "");
}
}
@@ -102,12 +106,6 @@ export class RenderedQuestion extends React.Component<QuestionProp & QuestionSta
this.props.setValue(this.props.question, value);
}
- // Toggle checkbox class
- if (event.target.type == "checkbox" && event.target.parentElement !== null) {
- event.target.parentElement.classList.toggle("unselected");
- event.target.parentElement.classList.toggle("selected");
- }
-
const options: string | string[] = this.props.question.data["options"];
switch (event.target.type) {
case "text":
@@ -194,17 +192,28 @@ export class RenderedQuestion extends React.Component<QuestionProp & QuestionSta
}
componentDidMount(): void {
+ // We don't want to set if we already have them in values.
+ if (this.props.question.id in this.props.values) {
+ return;
+ }
+
// Initialize defaults for complex and nested fields
const options: string | string[] = this.props.question.data["options"];
- const values = this.props.values[this.props.question.id];
+ let values = this.props.values[this.props.question.id];
switch (this.props.question.type) {
case QuestionType.Checkbox:
- if (typeof options === "string" || !(typeof values === "object") || !values) {
+ if (typeof options === "string") {
return;
}
+ if (!(typeof values === "object") || !values) {
+ values = {};
+ }
+
options.forEach((option, index) => {
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
+ // @ts-ignore
values[`${("000" + index).slice(-4)}. ${option}`] = false;
});
this.props.setValue(this.props.question, values);