Refactoring potentially complex template - meteor

Let supplier be documents (with code, names, and many other fields).
I have a component
export class SuppliersDetails extends MeteorComponent {
supplier: any;
invalidKeys: Object; // array <key> => <error message>
and a form
<div>
<input [(ngModel)]="supplier.code" [class.invalid]="invalidKeys['code']" id="code" type="text" class="validate">
<label for="code" [class.active]="supplier.code || invalidKeys['name']" [attr.data-error]="invalidKeys['code']" >Code</label>
</div>
that allow me to edit it.
How could I refactore my component/template, to lighten my template ?
Here it's only 1 field, and only the display of invalidKeys message is handled. But I have 8 fields and some specific logic to add. This will get unreadable.
I am looking for something like
<div>
<input plsDoItAllAndUseThatId='code'></input>
<label plsDoItAllAndUseThatId='code'>Code</input>
</div>
But I have no idea of the design, any idea ?

I would suggest looking into dynamic forms as described in the cookbook section of angular2 docs. The key here is to separate the business logic out of the form itself, such as by creating:
A questions object that will hold all the input properties
A service that will create all the generate all the questions needed by a specific form
A generic component that will loop through a list of questions and bind all the question properties to the input

This would be a good time you could use an attribute directive.
https://angular.io/docs/ts/latest/guide/attribute-directives.html#!#write-directive
You could write it as an attribute like you did in what you want to do. With that you can manipulate the element in the directive to add other attributes if you want or do whatever.
That would make it pretty slick. I'm a fan of this kind of stuff.
Lots of cool stuff you can do with that if you get creative.

Related

Custom validation in react-bootstrap forms not working

I'm trying to add custom validation logic to my react-bootstrap forms, but isInvalid doesn't seem to be respected. As soon as validated={true} is set on the form, it always validates non-empty strings, regardless of isValid or isInvalid. The invalid message is displayed, but the field shows as green. See here:
Here is the offending code:
<Form noValidate validated={formValidated} id="bidForm">
<Form.Group className="mb-3" controlId="formBasicBidding">
<Form.Label>Bid Amount</Form.Label>
<InputGroup hasValidation className="mb-3">
<InputGroup.Text id="inputGroupPrepend">$</InputGroup.Text>
<Form.Control
required
value={bidAmount}
isInvalid={!(parseInt(bidAmount) > 0) && formValidated}
onChange={e => setBidAmount(e.target.value)}
/>
<InputGroup.Text id="inputGroupAppend">.00</InputGroup.Text>
<Form.Control.Feedback type="invalid">
Please select a dollar amount {`>`} 0
</Form.Control.Feedback>
</InputGroup>
</Form.Group>
<...>
</Form>
I was able to get it to work using a pattern= regex on the input, but I'm planning to do more complex validation where a regex won't be sufficient. How can I get react-bootstrap to follow isValid and isInvalid properly? Thanks!
The docs don't do a great job of making this clear, but the form-level validated attribute hooks directly into HTML5's native validation library and can't be used simultaneously with other validation techniques. So if you're using the native option and an input doesn't violate any of the native validation options (required, pattern, etc), then the input will be considered valid. Since you don't have any of the native validation attributes besides required on your bid input, "foo" is valid as far as React-Bootstrap is concerned.
(If you're thinking 'well that's bad code design to let you use both simultaneously', I'd tend to agree with you.)
You'll note that with your current code, if you enter "foo" and submit the form the element actually does have an is-invalid class applied to it, but it's also got the :valid psuedo-selector applied to it because the entire form was validated, which seems to take precedence from a CSS perspective:
The best solution here is to use either the native HTML5 validation option (detailed here) or roll your own (with or without a helper library like Formik), but not both simultaneously.
If you're trying to avoid validating until the input is actually in a "dirty" state (e.g. the user filled it out or submitted the form), you can do something like this (CodePen here):
<Form.Control
required
value={bidAmount}
isInvalid={!(parseInt(bidAmount) > 0) && (bidAmount.length || formSubmitted)}
onChange={(e) => setBidAmount(e.target.value)}
/>

How to get input values from mgt-people-picker when a FORM is submitted

I'm using mgt-people-picker from within an ASP.Net Razor application, using a ProxyController to get all the data from the Graph API.
Everything is working fine.
Now I want to get the infos from a Form I've created, containing a people list, from the mgt-people-picker element :
From my ASP.NET backend, once the form is submitted; I have all the info from my inputs, except the mgt-people-picker element.
Anyone knows a simple solution to get the list of people form the input text, issued during the POST action ?
Or should we use a javascript trick ?
Ok, if anyone has the same issue, here is the solution, after a LOT of investigations.
You have to use the template of <mgt-people-picker> with data-type=selected-person.
In this template section, you need to add
An <mgt-person> with the correct properties (That I've found in the source code)
An <input type=hidden /> to store the values:
<mgt-people-picker>
<template data-type="selected-person">
<input type="hidden" value="{{person.userPrincipalName}}" name="people" id="people" />
<mgt-person view="oneLine" person-details="{{person}}" fetchImage=true></mgt-person>
</template>
</mgt-people-picker>
From within your backend handler, you will get all the persons selected in the Request.Form["people"] property
public void OnPost()
{
foreach (var personSelected in Request.Form["people"])
Debug.WriteLine(personSelected);
}
The solution is elegant and easy to use & understand.
Unfortunatelly, the documentation lacks details on the customization, especially on templates :)

Redux Form Fields Component and Validation

I am using the redux to hide and show components based on a value.
The Redux form documentation mentions the following:
Connecting to multiple fields should be used sparingly, as it will require the entire component to re-render every time any of the fields it is connected to change. This can be a performance bottleneck. Unless you absolutely need to, you should connect to your fields individually with .
I am unclear if my solution to hiding and showing fields based on radio buttons is good enough to use Fields giving the warning to use sparingly.
Can you please clarify if my component merits enough reason to use Fields. If not, what is an alternative way to implement?
Also, how does fields implement validations?
<div>
<form>
<Fields
component={RadioButtonGroupField}
names={['radioButtonGroup', 'nameTextField', 'nickNameTextField']}
/>
</ form>
</div>
function RadioButtonGroupField(fields) {
return(
<div>
<RadioButtonGroupComponent
{...fields.radioButtonGroup.input}
{...fields.radioButtonGroup.meta}
/>
{
(fields.radioButtonGroup.input.value === 'name' ||
fields.radioButtonGroup.input.value === 'both') &&
<NameTextFieldComponent
{...fields.radioButtonGroup.input}
{...fields.radioButtonGroup.meta}
/>
}
{
(fields.radioButtonGroup.input.value === 'nickname' ||
fields.radioButtonGroup.input.value === 'both') &&
<NicknameTextFieldComponent
{...fields.radioButtonGroup.input}
{...fields.radioButtonGroup.meta}
/>
}
</div>
);
}
There is another way you could do that, selecting the specific value using redux-form selectors (http://redux-form.com/6.0.5/docs/api/Selectors.md/) from the redux store in your mapStateToProps and then conditionally rendering certain components.
However, I think that Fields is exactly what you should use in this circumstance. I think that warning is largely to warn people not to go and put their entire form into Fields, having those 3 fields rerender is no big deal.
The thought process that led to the creation of Fields in the first place is probably the best way to get a handle on this: https://github.com/erikras/redux-form/issues/841

How to use the validation constraints in <g:select/> tag?

How do I use the validation constraints I have in the domain model automatically in the <g:select/> tag of my view, or is this not possible?
In my domain class, I have an int property with a size constraint:
int texture
static constraints = {
texture range:0..8
}
Now, in my view I want to use a select to allow the user to choose the proper value. I currently have this:
<g:form action="save">
<div class="fieldcontain ">
<label for="foamScore.texture">
Foam Texture
</label>
<g:select name="foamScore.texture" from="${0..8}"/>
</div>
</g:form>
I would like to avoid repeating the 0..8 part in the view if possible.
Grails jquery-validation-ui plugin will perform client side validation using server side GORM constraints. This way you can avoid duplicating the validation logic on the client side.
Here is the link to the plugin
http://grails.org/plugin/jquery-validation-ui

Drupal views - splitting up the exposed form possible?

I need to display part of the exposed form in my page's sidebar, and the rest of the form and content in the $content area. There's really no good way that I can find to do this. I sort of got it to show up in a way by making a "block" view with "exposed form" set and then trying to only show the part that i needed through .tpl files. The problem is that then, when the submit button is clicked (the submit button is in the $content area), then the filters that are in the sidebar are not taken into account.
Some lateral thinking... Why not explore CSS-only options? You can place that form element playing with position:absolute ? Or (considering is a right-sidebar) float:right and then some negative right margin to push it to the sidebar? If you are using 960 grid system, play with pull and push classes.
First I am going to answer your question, then I will explain why you are asking the wrong question:
If you build the form outside of the formapi, you might have some luck. This will get upgly and will require you to take a lot of extra care about attack-vectors such as mass-assignment.
views_some_view.tpl.php:
<form name="input" action="/link/to/view" method="get">
Country: <input type="text" name="country" />
my_custom_exposed_view.module:hook_block()
City:
That would make a form, which in most situations will start with <form>, have some input fields, then have a lot of random HTML, then some more input fields and then the closing .
As you may know, a <input type="submit" value="Submit" /> will only post everything of the form tags it is enclosed in. The submit button in the following HTML:
<form name="input_1" action="/link/to/view" method="get">
Country: <input type="text" name="country" />
</form>
<form name="input_2" action="/link/to/view" method="get">
City: <input type="text" name="city" />
<input type="submit" value="Submit" />
</form>
will only send the City. These are not the droids you are looking for.
It will need to be one, big form, but since everything between form and /form is very dynamic, and contains a large quantity of HTML, including potential other forms, this is really not what you want. Moreover: a blocks appearance (shown/not-shown) is controlled completely independent of the content. You will need a lot of sturdy code to ensure the block a) never shows up when the starting form tag is not present, and b) the block will guaranteed to be shown when that opening form tag is present. Else you have not just invalid HTML, but broken HTML that will truly render your page unusable in most cases.
You simply don't want a part of the form in a block and the other part in the content.
However, you want it visualised as if one part is in the body, the rest in a sidebar.
The good news, is that with HTML presentation structure are independant. That is where your solution lies.
Give your form-fields good ids and classes. You could use a hook_form_alter to change existing forms, but you probably simply just want to create the HTML for that entire form yourself. The theme layer allows that.
Use CSS to pick out either single form-fields by ID and position:absolute them into the correct place. Or pick out classes of fields by CLASS and position:relative them into the correct place.
Make a simple identification-routine that allows adding a class to the body-tag. (see below).
Add some CSS to shift the sidebar lower, making space for the form-fields to be moved in, when that class is in the body-tag.
<body class="<?php print $splitform ?>">
function my_themename_preprocess_page() {
if ($GET['q'] == 'path/to/view') {
$vars['spliform'] = "splitform"
}
}
From the above explanation I am assuming that you are printing same form in block and in content area and you are hiding some part of form in page.tpl , if this is true then you can use hook_form_alter() in your custom module then
Store the value of the form element(present in block) in global variable.
Now use that global variable and set form element(present in content area, this form element is not visible to user).
Provide more information if you implemented other way.
Regards,
Chintan.
There is a related issue here:
https://drupal.stackexchange.com/questions/3827/multiple-copies-of-views-filter-form-exposed-filters
which describes how to duplicate your filters. However it seems like an ugly hack.
A bit cleaner seems this solution mentioned in #6:
http://drupal.org/node/641838#comment-3247748
Haven't tested it out, but it looks good.
It will still give you some overhead (duplicate views) but it might be the easiest way doing this using views.
On the other hand you might write a module and build your own custom filter block which hooks into your view. Here is a blog post about this:
http://www.hashbangcode.com/blog/creating-custom-views-filters-exposed-form-element-drupal-6-561.html
If you use something like context you could get the exposed filters block to display twice in the same page. You could then use CSS to hide the fields you don't want to do display in each form.
The fundamental problem you're having is that to have the two forms in different places, they'll each have their own form element - when a submit is triggered, only the form fields within the same form element are sent. You need to move them into one form, or rely on JavaScript to gather the fields from both forms and construct the post.
You could create the block as an empty div and have javascript from the main page populate it with the secondary filter form and whatever else you need in there. Again, you could use javascript to copy the form values from the block form to hidden fields in the main form on submit. That gives you all the control you need from one place (the node output). Only caveat is that it relies a lot more on javascript to join it all together.

Resources