Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(elm): Introduce form validation library #63

Merged
merged 9 commits into from
Aug 15, 2017

Conversation

pmrukot
Copy link
Collaborator

@pmrukot pmrukot commented Jul 22, 2017

Summary
Introduces form client form validation.

Related issues
#61

@pmrukot
Copy link
Collaborator Author

pmrukot commented Jul 23, 2017

Update: Added advanced validators with regex, form is being cleared upon successful submission.
Would love to add Toast notifications if the submission was successful or not, but waiting for:
#59

@@ -27,7 +28,25 @@ update msg model =
{ model | user = response } ! []

OnQuestionCreated response ->
model ! []
case response of
RemoteData.Success responseData ->
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually I'm not sure what's the point of using RemoteData since we are ignoring all of its privileges. The main cause for using it is the fact that we can distinguish between having loaded empty or not yet having loaded data etc. Seeing how we deal with this everytime makes me cringe and rethink if we should really use it at all if that's the way we're using it. I mean, we can always say that we will implement rest of the pattern checks later, but we both know it's one of the lowest priority things.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should use RemoteData. Maybe this particular piece of code is not the best example but the abstraction layer it adds is actually nice. As a developer you don't need to worry about all the edge cases that can be returned from the server.


validationErrors =
possibleFields
|> List.map (\name -> Forms.errorList model.panelData.createQuestionForm name)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For me it works as the Elixir's style of aliasing nested modules - I would put let createQuestionForm = model.panelData.createQuestionForm to get it of this dot army.

newCreateQuestionForm =
Forms.updateFormInput oldCreateQuestionForm "question" ""

evenNewerCreateQuestionForm =
Copy link
Collaborator

@mrapacz mrapacz Jul 26, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Haven't checked that, but instead of these three createQuestionForm lets we could do with one using pipe chains. How about createQuestionForm -> updateFormInput -> updateFormInput?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Basically if you define bindings in let area only to use them in the next binding in the same let area, that suggests that you could actually just go ahead and use a pipechain.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Im not sure how to handle it in nice way 😑

oldPanelData =
model.panelData
possibleFields =
[ "question", "answers", "subject" ]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I totally wouldn't hardcode these (definitely not in Update.elm, I say we stick to only having logic here, not data). Maybe we could find a cozy place for constants like that? We could put it in appropriate Models.elm or Constants.elm file.

div []
[ p [] [ text "Enter answer below, separate all posibilities with comma:" ]
, input
[ placeholder "4,cztery"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Polish -> English

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the views could be split to more functions, but maybe I'll do it when #56

Copy link
Collaborator

@mrapacz mrapacz Jul 26, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mrapacz elmrefactor when

listRooms : WebData RoomsData -> List String
listRooms result =
case result of
RemoteData.Success roomsData ->
List.map (\room -> room.name) roomsData.data
"" :: List.map (\room -> room.name) roomsData.data
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, the "":: part is impressive and illegible. What does it actually do? I'm sure we can come up with a better way of solving this problem

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Validation library does not provide default values. So this is a dirty hack to have empty string at the beginning to force user to choose something. If the user would like to create a new question to the first displayed category he would need to choose something else and get back to it and then hit submit.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we need better solution for a dropdown menu though.

{ model | panelData = { oldPanelData | newQuestionContent = questionContent } } ! []
{ model
| panelData =
{ oldPanelData | createQuestionForm = Forms.updateFormInput oldPanelData.createQuestionForm name value }
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here, you get rid of the dots using improved imports or cool variable bindings in let area just above and you're left with createQuestionForm = updateFormInput createQuestionForm name value. Seems more legible. I also think the naming could be better here. What if we changed createQuestionForm to questionForm? The create verb confuses me a lot as I imagine it is a name of a function that actually creates a questionForm

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should leave Forms prefix so we know where this function comes from.

if List.isEmpty validationErrors then
( model, createQuestionWithAnswers model )
else
model ! []
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens if there actually are errors? (serious question, what do we want to do, react somehow - flash info message or just leave it and let user figure out why it's not working?)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was thinking about displaying Toasties but Im still waiting for #59 to be merged.

in
{ model | panelData = { oldPanelData | newAnswerCategory = answerCategoryToId } } ! []
if List.isEmpty validationErrors then
( model, createQuestionWithAnswers model )
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's a matter or #56 but I wouldn't pass the whole model to any function (apart from main Update etc). I believe that we should always only pass one data structure from our model. Well, what if I would then need to pass like three different structures from our model, eh? one could ask. I believe that if we split our state well, these all three different structures should end up in one bigger structure that aggregates them.

Copy link
Collaborator

@mrapacz mrapacz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@pmrukot Bring ye the whole answers into the discussion.

@pmrukot pmrukot force-pushed the feat/multiple-asnwers-support-client branch from 4da66e7 to fcdb031 Compare August 12, 2017 15:31
@pmrukot
Copy link
Collaborator Author

pmrukot commented Aug 12, 2017

@mrapacz I've updated according to your suggestions, only not sure how to handle pipe chains. For me It would be also good to merge it and adjust later since we need to move forward.

Copy link
Collaborator

@mrapacz mrapacz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks acceptable imho, looks really neat. Let's leave it like this for now, I may fix the small things while doing the elm refactor.

@pmrukot pmrukot merged commit 526fdde into master Aug 15, 2017
@pmrukot pmrukot deleted the feat/multiple-asnwers-support-client branch August 15, 2017 08:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants