Angular material 2 share reactive form between components - angular-material2

I have the following component template
<form [formGroup]="form" (ngSubmit)="onSubmit()">
<section>
<mat-form-field>
<input matInput formControlName="firstName" placeholder="First name" />
</mat-form-field>
</section>
<child-component [form]="form"></child-component>
<button type="submit" mat-raised-button color="primary">
<span>Submit</span>
</button>
</form>
And the following child component template
<section [formGroup]="form">
<mat-form-field>
<input matInput formControlName="emailAddress" placeholder="Email address" />
</mat-form-field>
</section>
Both fields are defined using reactive approach in the parent component and set as required.
When submitting the form, only the field inside the parent component has class mat-form-field-invalid and is shown in red.
Both fields appear as invalid at FormControl instance though.
I have created the following stackblitz to reproduce the issue
https://stackblitz.com/edit/angular-material2-issue-7x45bp

If I'm not mistaken, your invalid form fields will only appear in red after they have been marked as touched, which you can force programtically on form submit if you so wish (just not so elegant, Reactive Forms - mark fields as touched).
Your required fields are missing the asterisk that usually exists next to the form field name to visually indicate that the field is required. To add that just add required="true" or alternatively [required]="someFunctionThatChecksFieldHasRequiredValidatorInFormGroup(fieldName)"

The easiest way to do this is to pass in the FormControl instead of the form:
<form [formGroup]="form" (ngSubmit)="onSubmit()">
<section>
<mat-form-field>
<input matInput formControlName="firstName" placeholder="First name" />
</mat-form-field>
</section>
<child-component [childControl]="form.get('emailAddress')"></child-component>
<button type="submit" mat-raised-button color="primary">
<span>Submit</span>
</button>
</form>
<section>
<mat-form-field>
<input matInput [formControl]="childControl" placeholder="Email address" />
</mat-form-field>
</section>
This is actually better for component re-usability anyway (if you also make placeholder a property).
Otherwise, you would probably need to have your child component implement ControlValueAccessor.

Related

thymeleaf 3 form action URL with parameters and get method not working

I am using Thymeleaf 3 in Spring Boot 2 web app. Below is the form code:
<form data-th-action="#{/props/r(pg=3)}" method="get">
<div class="form-check form-check-inline">
<input class="form-check-input" type="checkbox" name="pt" id="p1" value="pr">
<label class="form-check-label" for="p1">P1</label>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" type="checkbox" name="pt" id="p2" value="pr2">
<label class="form-check-label" for="p2">P2</label>
</div>
<button type="submit" class=" mb-4">Search</button>
</form>
Unfortunately when I used method get for the form, it does not append ?pg=3 in the submitted URL, the URL looks like /props/r? if no checkbox is selected. If checkbox is selected the URL looks like /props/r?pt=p1
the pg=3 part is missing.
How to fix this problem?
The problem is that you have an action #{/props/r(pg=3)} -- which translates to /props/r?pg=3 and your form is also method get. If you have parameters in both the action and the body of the form (and usemethod="get"), browsers will not combine them. Instead, the parameters of the action are removed and replaced with the paramters in the body of the form.
This is why ?pg=3 is removed and replaced with the checkbox parameters. Either use post instead, or include pg as a hidden form element.
Instead of putting pg as parameter at the form url, consider putting it inside a hidden field like below.
<input type="hidden" name="pg" value="3">

How to Apply form validation inside data table in angular2

I am trying to apply required field validation for text-box which is inside data table template.
Required field validation message pop up properly but as there is no form tag i was not able to check form.valid in component.
Please find below code:
<data-table id="user-grid"(reload)="reloadItems($event) [items]="userData">
<data-table-column [header]="'UserName'">
<template #dataTableCell let-item="item">
<span>
<input type="text" [(ngModel)]="item.UserName" class="form-control" required #UserName="ngModel" name="UserName"/>
<span class="text-danger" *ngIf="(UserName.errors != null && UserName.errors.required && (UserName.dirty))">
Please enter user name.
</span>
</span>
</template>
</data-table-column>
<data-table-column [header]="'Action'" >
<template #dataTableCell let-item="item">
<a title="Save" (click)="save(item)" class="btn green btn-sm">
</a>
</template>
</data-table-column>
</data-table>
Any help will be appreciable.
Put the datatable element inside the form tag having ngForm. It would fire the form validations.
Please see below:
<form #testform="ngForm">
<data-table>
</data-table>
</form>

ruby forms in div elements

I'm having an issue where the form generated with ruby isn't included inside my #content div, is this because the form is generated after the html is read by the browser (sorry if I sound like a moron on this)
-- edit update - view source --
The code below generates with the email box and submit button outside of the content box
<div id="content">
<!-- text here -->
<form accept-charset="UTF-8" action="/password_resets" method="post">
<div style="margin:0;padding:0;display:inline">
<input name="utf8" type="hidden" value="✓" />
<input name="authenticity_token" type="hidden" value="afmtpSAc93w1uMcnouhY9XmbVTM7fE1VNFvZKnp0kMs=" />
</div>
<div class="field">
<input id="email" name="email" placeholder="email#website.com" type="text" />
</div>
<div class="actions">
<input name="commit" type="submit" value="Reset Password" />
</form> </div>
</div>
I'm not sure I got the question right, but in the html above the last </form> </div> should be </div> </form>
figured it out after visiting this link
Is it correct to use DIV inside FORM?
once I removed the div's for field and action it cleared everything up

ajax field validation in struts2 not reloading the same form

I've been trying to use the field-validation framework in Struts2 and have it implemented. The problem is when doing an AJAX call with jquery tags, it targets a resulting div when I want to reload the same page with the fielderror.
<div class="myform">
<s:form id="userForm" action="users" theme="simple">
<h1>Search for Users</h1>
<p><s:fielderror /></p>
<label>Username
<span class="small">Add your name</span>
</label>
<s:textfield id="username" name="username"/>
<label>Point Minimum
<span class="small">Min. 0 points</span>
</label>
<s:textfield name="pointMin"/>
<label>Point Maximum
<span class="small">Max. 5000 points</span>
</label>
<s:textfield name="pointMax"/>
<label>Rate Minimum
<span class="small">Percentage</span>
</label>
<s:textfield id="rateMin" name="rateMin"/>
<label>Rate Maximum
<span class="small">Percentage</span>
</label>
<s:textfield id="rateMax" name="rateMax"/>
<s:hidden name="searchButtonHit" value="%{true}"/>
<sj:a formIds="userForm"
targets="listingDisplay"
button="true"
validate="only"
type="submit"> Search
</sj:a>
<div class="spacer"></div>
</s:form>
</div>
<div class="spacer"></div>
<div id="listingDisplay"></div>
The <sj:a> tag targets the listingDisplay div so the fielderror as well as the same form is loaded underneath which looks very strange. Is there a better way of doing this? Thanks!
Have a look at the below validation link. It adds a string errorhere to the error message and checks for it after response. You can also do this to reload the page and the reload code can be written in 's onSuccessTopics.
Ajax Validation
Method 2
Very simple but may not work on all browsers.
Set the targets attribute of
<sj:a targets="myform">
to the same div, within which the form exists.

Jquery Validation plug-in custom error placement

Using the jQuery Validation plug-in for the following form:
<form id="information" method="post" action="#">
<fieldset>
<legend>Please enter your contact details</legend>
<span id="invalid-name"></span>
<div id="id">
<label for="name">Name: (*)</label>
<input type="text" id="name" class="details" name="name" maxlength="50" />
</div>
<span id="invalid-email"></span>
<div id="id">
<label for="email">Email: (*)</label>
<input type="text" id="email" class="details" name="email" maxlength="50" />
</div>
</fieldset>
<fieldset>
<legend>Write your question here (*)</legend>
<span id="invalid-text"></span>
<textarea id="text" name="text" rows="8" cols="8"></textarea>
<div id="submission">
<input type="submit" id="submit" value="Send" name="send"/>
</div>
<p class="required">(*) Required</p>
</fieldset>
</form>
How can I place the errors inside the span tags? (#invalid-name, #invalid-email, #invalid-text)
I read the documentation about error placement but I did not get how it works.
Is it possible to handle each single error and place it in the specified element?
Thank you
You can also manually add error labels in places you need them. In my particular case I had a more complex form with checkbox lists etc. where an insert or insert after would break the layout. Rather than doing this you can take advantage of the fact that the validation script will evaluate if an existing label tag exists for the specified field and use it.
Consider:
<div id="id">
<label for="name">Name: (*)</label>
<input type="text" id="name" class="details" name="name" maxlength="50" />
</div>
Now add the following line:
<label for="name" class="error" generated="true"></label>
which is standard error label:
<div id="id">
<label for="name">Name: (*)</label>
<input type="text" id="name" class="details" name="name" maxlength="50" />
</div>
<div id="id-error">
<label for="name" class="error" generated="true"></label>
<div>
jQuery will use this label rather than generating a new one. Sorry I could not find any official documentation on this but found other posts that came across this behaviour.
This is a basic structure, you can use whatever selector you would like in the method. You have the error element and the element that was invalid.
jQuery.validator.setDefaults({
errorPlacement: function(error, element) {
error.appendTo(element.prev());
}
});
Or to target the ID, you could do
jQuery.validator.setDefaults({
errorPlacement: function(error, element) {
error.appendTo('#invalid-' + element.attr('id'));
}
});
Not tested, but should work.
I found that using .insertAfter rather than .appendTo works:
jQuery.validator.setDefaults({
errorPlacement: function(error, element) {
error.insertAfter('#invalid-' + element.attr('id'));
}
});
I'm using the metadata extension with the validator.. (note, I'm setting it to use the data-meta attribute on the markup...)
<input ... data=meta='{
errorLabel: "#someotherid"
,validate: {
name:true
}
}' >
then in code...
jQuery.validator.setDefaults({
errorPlacement: function(error, element) {
error.appendTo($(
$(element).metadata().errorLabel
));
}
});
I've been using the metadata for a lot of similar functionality, which works rather nicely... note, I used the single ticks (apostrophes) around the meta data, this way you can use a JSON serializer server-side to inject into that portion of the tag (which should use double-quotes around strings)... a literal apos may be an issue though, (replace "'" with "\x27" in the string).

Resources