This is the 25th day of my participation in the November Gwen Challenge. Check out the event details: The last Gwen Challenge 2021
[thousands of words long, stay up late to update, original is not easy, a lot of support, thank you]
preface
Hello, everyone. Today I will take you to continue to improve our questionnaire function. So far, our questionnaire function has realized the basic functions of questionnaire theme configuration, questionnaire results submission, questionnaire results saving and backfilling, questionnaire results display and so on. It seems that a questionnaire function has been implemented, but there is another important function that has not been implemented, that is, the data validity check function. Think about it if there is no data validity check, open a questionnaire and submit it directly without filling in anything, it will lose the significance of the questionnaire. Therefore, this paper will add data validity verification function on the basis of the previous sharing.
Requirements describe
To add data validation, we need to implement the following requirements (function points)
- Whether each topic is mandatory can be determined by the publisher
- If the topic is mandatory, add a red asterisk (*) before the title
- When the user clicks the submit button to verify the validity of the data, if there is an unfilled questionnaire topic, an information prompt (invalid data) should be given under the corresponding questionnaire title and the code should stop and continue
- After invalid data is added, the red message disappears automatically
- When the page first loads, all data is empty, so the red message should not be displayed until the submit button is clicked
Requirements have been basically clear, the following step by step in accordance with these requirements to achieve data validity verification
Configuring a Data Source
The above requirements have clearly required that whether the questionnaire topic is mandatory or not should be defined by the questionnaire publisher, while it is impossible for the questionnaire publisher to modify the code, so we have to start from the data source. The general idea is to add a required field to each survey topic in the data source to indicate whether the topic is required. This field is then used to control whether the page displays a red asterisk and a red prompt. The modified data source code is as follows:
// public/data.json
// Add a Required field of type Boolean
{
"data":[
{"id":1."title":"Vue3.0 easy to learn?"."required": true}]."radios":[
{"id":1."title":"Are you satisfied with the company's benefits?"."items": ["Very satisfied."."Satisfied"."Basically satisfied"."Dissatisfied"] {},"id":2."title":"Are you satisfied with your current income?"."items": ["Very satisfied."."Satisfied"."Basically satisfied"."Dissatisfied"]."required": true}]."checks":[
{"id":1."title":"What other benefits would you like the company to add?"."items": ["Get a raise"."Pay for your food."."Send girlfriend"."All of the above"]."required": true}]."inputs":[
{"id":1."title":"What do you want to say to our company?"."required": true},
{"id":2."title":"Just say something."."required": true}]."stars":[
{"id":1."title":"Please give this share a mark!"."items": ["Bad"."Disappointed"."General"."Very good"."Very good."]."required": true}}]Copy the code
Encapsulate the header.vue component
According to the second requirement above, a red asterisk (*) is required to be added before each required questionnaire topic. Therefore, we need to modify each questionnaire topic component by adding a red asterisk prompt before its title and a text message prompt with red font below it. From this analysis, we found that the code to be modified in each component is the same and it is a repetitive work. If there is a similar behavior to change the title in the future, we still have to modify each component to do the same work. We simply put the title part of the questionnaire into a separate package into a sub-component:
- Create a header.vue component and copy the header from the original component (< h3> {{title}}
).- Then add a SPAN tag before the title in the H3 tag, wrapped with a red asterisk (*), and add a V-show directive with a value of required to the SPAN tag to control whether the red asterisk is displayed
- Add a div tag at the bottom of h3 with a height of 15px (so that the page doesn’t jump when the red text is displayed and hidden), and add a sub-div to the div to display the red text, and add a V-show command to control the display and hiding of the red text
- Define three props properties for this component:
- Title: Used to display the title of the questionnaire
- Required: Controls whether the file subject is required
- Validator: Validator that verifies whether the results of the current questionnaire are valid data (true by default). This, in conjunction with the Required attribute, controls whether the red text is displayed
- Finally, add a flash animation to the red text prompt for page effect
The complete code is as follows:
<template>
<h3><span v-show="required" class="required">*</span>{{ title }}</h3>
<div style="height:15px">
<div v-show="required && ! validator" class="validator">This is mandatory, don't be lazy oh, please select something or write something!</div>
</div>
</template>
Copy the code
export default{
props: {title: {type:String.required:true
},
required: {type:Boolean.default:false
},
validator: {type:Boolean.default:true}}}Copy the code
.required{
color:red;
}
.validator{
font-size:12px;
color:red;
animation: valid 2s infinite;
}
@keyframes valid{
0%{
opacity: 0;
}
25%{
opacity: 0.5;
}
50%{
opacity: 1;
}
75%{
opacity: 0.5;
}
100%{
opacity: 0; }}Copy the code
Modify the topic component of the questionnaire
After wrapping the header sections into components, we need to modify each of the questionnaire topic components:
- Template part: Replace the original H3 tag with our wrapped Header component. One caveat: When importing header components with import, do not name them header, as this will conflict with html5’s native header tags.
- Add the two props properties required and validator corresponding to the two props in header.vue
The vote.vue component is used as an example to show the modified code. The other components are the same:
<! -... Omit -- -- >
<template #header>
<myheader :required="required" :validator="validator" :title="title" />
</template>
<! -... Omit -- -- >
Copy the code
/ /... omit
props: {/ /... omit
required: {type:Boolean.default:false
},
validator: {type:Boolean.default:true}}/ /... omit
Copy the code
Modify home.vue component to add data validity verification logic
The realization of data validity verification function in this component is slightly complicated, and IT took me a long time to know where to start. Finally, after continuous attempts, I found the idea and realized the data validity verification function bit by bit. The following are the initial ideas and problems encountered
- Since all questionnaire topics are generated in a loop, we cannot directly manipulate the DOM to obtain a specific topic, and thus cannot determine which topic is filled in and which is not filled in. But there is no way, after careful analysis found: Each theme is looped with a unique key, so we can save each theme to a temporary variable called validateResult (object). The key is the object’s property, and the property value is set to false (the default validation fails). As far as we can see, only the calculation property recoverResult is called each time along the loop, so we place the initialization of this object in the function returned by the calculation property.
- When the user starts to fill out the questionnaire, the select event for each component is triggered, so we can update the value of the questionnaire subject in validateResult based on the selected result in the method getValue bound to this event (that is, if the data is valid, update the corresponding value to true to indicate validation).
- In the Submit button event (submit method), the validateResult is iterated, and if all of the properties are true, the validation has passed, otherwise the code should be stopped immediately if any value is false.
- Modify the template content to add required and Validator attributes for each questionnaire topic component to control whether it is required and whether the red text prompt is displayed
The revised code for the home.vue component is as follows :(note that the code shown below is not the final version (there are bugs), so don’t be too quick to type, there are Easter eggs behind)
<template>
<! -... Omit -- -- >
<! -- Only show some modified code, other original code omitted -->
<vote :required="item.required" :validator="validateResult[`vote${item.id}`]" />
<myradio :required="radio.required" :validator="validateResult[`radio${radio.id}`]" />
<mycheck :required="check.required" :validator="validateResult[`check${check.id}`]" />
<myinput :required="inp.required" :validator="validateResult[`input${inp.id}`]" />
<mystar :required="star.required" :validator="validateResult[`star${star.id}`]" />
<! -... Omit -- -- >
</template>
Copy the code
// Show only part of the modified code, others omitted
const submit = () = >{
for (const key in validateResult){
if(! validateResult[key]){return; }}}/ /... omit
const getValue = (val, title, flag) = >{
if(flag.indexOf("vote") > =0) {/ /... omit
validateResult[flag] = val.supValue > 0 || val.oppValue > 0;
}else{ validateResult[flag] = !! (""+val).trim()
}
}
const recoverResult = (title, flag) = > {
return function(title, flag){
validateResult[flag] = false; }}return {
validateResult
}
Copy the code
Through a toss and toss finally had rudiment, can’t wait to run up to see the effect found: ah
- We have the red asterisk in front of the title
- The red text prompt information under the blank questionnaire topic also appeared and flashed
- When the submit button is clicked, the submit function is also blocked
It looks like the validation is there, and everything is there. But, but, but, after going back to the original requirements and testing it line by line, there are a few minor problems:
- When the questionnaire results were completed, the red text prompt message still existed and did not disappear automatically
- Reason: The validateResult object we originally defined was not a reactive object
- Solution: Define validateResult as a reactive variable
- When the questionnaire page is opened for the first time or the page is reloaded and the submit button is not clicked, all the required items will be displayed in red text (in the case of the first time or the page is reloaded but the submit button is not clicked, the red text should not be displayed and will be prompted only when the submit button is clicked).
- Cause: The function returned by recoverResult to calculate the property is called each time the page is reloaded, and the result value of all topics is updated to false each time, that is, the verification fails
- Solution: Define a reactive variable init with an initial value of true to indicate that the current page has been opened or reloaded for the first time and the submit button has not been clicked. Update this value to false when the submit button is clicked. Then use init and validateResult to control whether the prompt is displayed or not (if init is true, no red prompt is displayed even if validateResult is false).
- When aNot requiredIf the result of the questionnaire subject is blank (other mandatory items are passed), clicking the submit button still fails to submit
- Reason: This is because when we check the validity of the data, we do not check whether the topic is mandatory or not, but all of them are validated (non-mandatory items are not required to check).
- Solution: Add a required parameter to the getValue and recovcerResult methods, and verify the validity of the data based on this parameter. If required is false, default the result value of the topic to true to indicate that the validation has passed.
The final code is as follows:
<template>
<! -... Omit -- -- >
<! -- Only show some modified code, other original code omitted -->
<! -- Add init validation, if the page is initially loaded, do not display the red prompt -->
<vote :required="item.required" :value="recoveryResult(item.title, `vote${vote.id}`, vote.required) || { supValue: 0, oppValue: 0, }" :validator="validateResult[`vote${item.id}`] || init" @select="getValue($event,item.title,`vote${item.id}`,item.required)" />
<myradio :required="radio.required" :value="recoveryResult(radio.title,`radio${radio.id}`,radio.required) || ''" :validator="validateResult[`radio${radio.id}`] || init" @select="getValue($event,radio.title,`radio${radio.id}`,radio.required)" />
<mycheck :required="check.required" :value="recoveryResult(check.title,`check${check.id}`,check.required) || []" :validator="validateResult[`check${check.id}`] || init" @select="getValue($event,check.title,`check${check.id}`,check.required)" />
<myinput :required="inp.required" :value="recoveryResult(inp.title,`input${inp.id}`,inp.required) || ''" :validator="validateResult[`input${inp.id}`] || init" @select="getValue($event,inp.title,`input${inp.id}`,inp.required)" />
<mystar :required="star.required" :value="recoveryResult(star.title,`star${star.id}`,star.required) || 0" :validator="validateResult[`star${star.id}`] || init" @select="getValue($event,star.title,`star${star.id}`,star.required)" />
<! -... Omit -- -- >
</template>
Copy the code
// Show only part of the modified code, others omitted
const state = reactive({
validateResult: {},init:true
});
const submit = () = >{
state.init = false;// Click the Submit button to set the value to false
for (const key in state.validateResult){
if(! state.validateResult[key]){return; }}}/ /... omit
const getValue = (val, title, flag, required) = >{
if(flag.indexOf("vote") > =0) {/ /... omit
state.validateResult[flag] = required ? val.supValue > 0 || val.oppValue > 0 : true;
}else{
// If this parameter is mandatory, the verification is performed based on the selected result. Otherwise, the value is changed to true to indicate that the verification succeedsstate.validateResult[flag] = required ? !!!!! (""+val).trim(): true; }}const recoverResult = (title, flag, required) = > {
return function(title, flag){
state.validateResult[flag] = !required;
}
}
Copy the code
Results show
At this point, a complete data validity check function is realized, and the final effect is as follows:
conclusion
In this sharing, the validity check function of questionnaire result data was realized. The seemingly simple data check was actually a little complicated to implement. It took nearly a day to perfect the function after a lot of trouble and continuous attempts.
This time to share here, like small partners welcome to like comments and attention oh!