how do I implement template variables in angular? - javascript

Im trying to pull the ngModel object for form validation but upon serving I'm getting an error at my template variable.
here is the code:
<form>
<div class="form-group">
<label for="courseName">Course Name</label>
<br />
<input type="text" id="courseName" ngModel name="courseName" #courseName="ngModel" required />
<br />
<div *ngIf="!courseName.valid" class="alert alert-danger">field is required</div>
<label for="category">Category</label>
<br />
<select name="category" id="category" class="form-control-lg" ngModel>
<option value="test">poop</option>
</select>
<div class="checkbox">
<label for="checkbox">
<input id="checkbox" type="checkbox" name="moneyBack" />30-day money back guarantee
</label>
</div>
</div>
<button class="btn btn-primary">Submit</button>
</form>
EDIT
After testing, I found that the problem arises when I assign the template variable, as well as I noticed that the "#" symbol in my code editor is not the same color as the tutorial I'm watching meaning that the editor isn't recognizing the syntax so its possible that this syntax is either deprecated (which is possible, the tutorial I'm following seems to be a little older) or I am implementing it wrong, what is the correct way to declare a template variable?
OR more importantly lol
what is the correct way to access the form-control object so I can get the .value, .pristine, .touched properties?
<#templateVariable ngModel name="test"> **No Error**
<#templateVariable="ngModel" ngModel name="test>**ERROR**
EDIT
EDIT
The issue was with naming ngModel and the field the same same
EDIT
here is a screenshot of the error
here is a screenshot of the import of ngModel

There are few things that you can check:
Import FormModule in app.module.ts file.
Change your code in the following way
<input type="text" id="courseName" [(ngModel)] = "courseName" name="courseName" #course="ngModel" required/>
[(ngModel)] and reference name must be different. If you put both same name to 'courseName' you will get reference error!

Use this way
[(ngModel)]="courseName"

Related

google apps script sidebar form Send button not working

I'm creating a google add on for sheets. The sidebar I'm working on is intended to be sort of help ticket submission, but way before I can develop that part of things, I'm not getting the submit button in the form to call the javascript function I want to build.
I've removed all of the form data from the html button call to activate a Logger.log. No dice.
I created a completely separate (and very simple) button to call a different function to call Logger.log. This also did not work.
I've double checked the form data, the send call, and the function.
I made sure the name of the function (sendMsg) is unique.
I think that the issue may not be in my code but in some other way the html and javascript (.gs) are connected.
here is the html form:
<div class="block form-group">
<form>
<label for="reason">Purpose of Contact</label>
<select id="reason">
<option selected>Help Request</option>
<option>Feature Request</option>
<option>Error Report</option>
<option>Other</option>
</select>
<label for="email">Email</label>
<input type="text" id="email" style="width: 200px;">
<label for="phone">Phone</label>
<input type="text" id="phone" style="width: 120px;" value = "optional">
<br>
<label for="translated-text">
<b>Message</b></label>
<textarea id="userMsg" rows="15" cols="35">
</textarea>
<br>
<input id="app" name="appSrc" type="hidden" value="COE">
<input type="button" class="action" name="helpRequest" value="SEND" onClick="google.script.run.sendMsg(
document.getElementById('reason').value,
document.getElementById('email').value,
document.getElementById('phone').value,
document.getElementById('userMsg').value,
document.getElementById('appSrc').value
)" />
</form>
</div>
and here is the function called:
function sendMsg(appSrc,reason,email,phone,userMsg) {
appV = appSrc;
reasonV = reason;
emailV = email;
phoneV = phone;
userMsgV = userMsg;
Logger.log('cheese');
}
Right now the form should simply result in a Logger.log message. At this point nothing happens.
In your situation, when "SEND" button is clicked, the script of sendMsg() at Google Apps Script side doesn't work.
You want to run sendMsg().
If my understanding is correct, how about this modification?
Modification point:
When I saw <input id="app" name="appSrc" type="hidden" value="COE">, appSrc is not id. By this, an error occurs at document.getElementById('appSrc').value, and sendMsg() didn't work. So if your script is modified, for example, please use app.
From:
document.getElementById('appSrc').value
To:
document.getElementById('app').value
Or
From:
<input id="app" name="appSrc" type="hidden" value="COE">
To:
<input id="appSrc" name="appSrc" type="hidden" value="COE">
If I misunderstood your question and this was not the result you want, I apologize.
In case anyone has the same issue as I had... onpress doesn't seem to work here. I had to change it to onclick.

How to get ElementRef reference from NgModel FormControl in NgForm in Angular 4+

In Angular 4+, I've following template driven form:
<form #addForm="ngForm" (ngSubmit)="onFormSubmit($event, addForm)" >
<div class="form-group">
<label for="item_name">Item Name</label>
<input id="item_name" name="item_name" [(ngModel)]="itemName"
#item_name="ngModel" autofocus class="form-control"
required minlength="4" maxlength="20"
aria-describedby="itemNameHelpBlock">
<small *ngIf="(item_name.invalid && item_name.touched)" id="itemNameHelpBlock" class="form-text text-error" >
Value must be at least 4 characters and must not exceed 20 characters
</small>
</div>
<div class="form-group">
<label for="item_type">Item Type</label>
<input id="item_type" name="item_type" [(ngModel)]="itemType"
#item_type="ngModel" class="form-control" required minlength="2"
maxlength="20" aria-describedby="itemTypeHelpBlock">
<small *ngIf="(item_type.invalid && item_type.touched)" id="itemTypeHelpBlock" class="form-text text-error" >
Value must be at least 2 characters and must not exceed 20 characters
</small>
</div>
<button class="btn btn-output-primary btn-lg" [disabled]="!addForm.form.valid">Add</button>
</form>
In the component section, I want to access the form field (ie item_name, item_type) as ElementRef so that I can access their corresponding DOM element through the nativeElement method of ElementRef class.
I've tried with #ViewChild but, it returns NgModel class object:
#ViewChild('item_name') item_name: ElementRef;
ngAfterViewInit() {
console.log(this.item_name); // it returns NgModel class object
}
But, I need to access the DOM HTMLElement of #item_name form field so that I can reset document focus to #item_name input field after every form submission. Now, I don't know how I can do it without directly accessing the DOM and I don't wanna directly access the DOM via DOM api.
I would be glad if I get some help here.
I would simply add read option to ViewChild query:
#ViewChild('item_name', { read: ElementRef }) item_name: ElementRef;
^^^^^^^^^^^^^^^
Stackblitz Example
See also
How to get reference of the component associated with ElementRef in Angular 2
Just to give a use case, you can point #item_name to ngModel to access some attributes of the model itself, for example if it's currently considered valid.
<input id="item_name" name="item_name" [(ngModel)]="itemName" #item_name="ngModel"
autofocus class="form-control">
<!-- here's where you can access the attributes if it's pointed to ngModel-->
<small [hidden]="password.valid">
The item name is not valid
</small>
If you don't need this rather fancy stuff, you can just remove it, as Andriy proposed. Then it's working out of the box with no further changes.
If you need to keep it however, you can give your input field an additional reference which you can use to get the ElementRef.
<input id="item_name" name="item_name" [(ngModel)]="itemName"
#item_name="ngModel" #itemNameField autofocus class="form-control">
You just have to reference the one that is not pointing to ngModel.
#ViewChild('itemNameField') itemNameField: ElementRef;
Angular does not complain about having multiple references on one field (as far as I tested it)
In your HTML, do not point template reference #item_name to ngModel, just leave it empty like:
<div class="form-group">
<label for="item_name">Item Name</label>
<input id="item_name"
class="form-control"
name="item_name"
[(ngModel)]="itemName"
#item_name
autofocus>
</div>
then, you can access DOM element using #ViewChild decorator (as you did) like:
this.item_name.nativeElement,
I noticed, you have a typo in your submit button: opening '[' is missing just before disabled property.
Plunker: https://plnkr.co/edit/XHqOiEBmuFrA3slZSlrD?p=preview

Angular 4 - Conditional CSS Classes

I'm working on an Angular 4 app, where we present the user with a login. The login may fail, and on return, we listen for the error:-
.subscribe(error => {
this.error = error;
});
This shows fine and we show this:-
<div *ngIf="error">
<p class="error-message">{{ error.ExceptionMessage }}</p>
</div>
Above this is a standard input field for username and password with a class. I wanted to be able to add an error class to this without doing the following:-
<div *ngIf="error">
<input type="email" class="form-control" />
</div>
<div *ngIf="!error">
<input type="email" class="form-control error-field" />
</div>
Is there a better way than rendering the input twice, on each side of the if?
Thanks!
You can do this using the class binding:
<input type="email" class="form-control" [class.error-field]="error">
yeah there's a better way using ngClass attribute like this:
<input type="email" [ngClass]="{'form-control': true, 'error-field': error}" />
I believe you are looking for NgClass or NgStyle:
https://angular.io/api/common/NgClass
https://angular.io/api/common/NgStyle

Form validation on generated fields with ng-messages

For a day I fiddled around with getting form validation to work with the new ng-messages on generated fields with no success. I read in the angular documentation and on a github issue ng-repeat is not supported by ng-messages because it does not interpolate its fields. So, I decided to go the jquery route build the dom myself compile it and replace the element with my generated code, which after of course I don't get to work either. So some help would be much appreciated. Here's my html:
....
<app-field ng-repeat="field in fields" field="field" ng-model="selected[field.name]" form="form" type="input"></app-field>
<fieldset class="form-group">
<label for="field1s">static field 1</label>
<input name="field1s" type="text" ng-model="selected['field1']" class="form-control" required="">
<ng-messages for="form['field1'].$error">
<ng-message when="required">Is required</ng-message>
</ng-messages>
<label for="field2s">static field 2</label>
<input name="field2s" type="text" ng-model="selected.field2" class="form-control" required="" ng-maxlength="10" ng-minlength="2">
<ng-messages for="form.field2s.$error">
<ng-message when="required">Is required</ng-message>
<ng-message when="maxlength">Max length 10</ng-message>
<ng-message when="minlength">MIn length 2</ng-message>
</ng-messages>
</fieldset>
I've added some statically typed fields too so i could monitor the data source and the form. The directive app-field generates the dom which is cooked up with some jquery soup but it turned out to work quite well. I mean the generated dom looks like it is supposed to but ... but compiled it does not agree with angular, angular doesn't throw any errors but it just refuses to bind the dynamic fields to the form correctly. It updates the underlying object but does not do form validation let alone trigger the ng-messages and according to this post: Angularjs: Form validation on input field generated by directive I see no reason why it shouldn't. Here's a plunk: http://plnkr.co/edit/ZzC4jS9M9Ev5i6gxUVxB?p=preview
Any help is appreciated...
You need to have ng-form element inside every ng-repeat for dynamic field validation to work. I have fixed the problem in below plunker for field 1.
http://plnkr.co/edit/xQTLDa3TptXky8KIcSsh?p=preview
<form name="form">
<ng-form name="myform">
<input name="field1s" type="text" ng-model="selected['field1']" class="form-control" ng-required="true" ng-pattern="/^[0-9a-zA-Z]+$/">
<ng-messages for="form.myform['field1s'].$error">
<ng-message when="required">Is required</ng-message>
<ng-message when="pattern">alpha error </ng-message>
</ng-messages>
</ng-form>
</form>
I have commented out the custom JQuery code you had written. Since it is no longer required.
Please refer to this - https://github.com/angular/angular.js/issues/10165 for more info. on this problem.

Parsley.js - Understanding and erroring on groups

I think I've misunderstood the use of groups in Parsley.js. What I had assumed is that groups could be used to not show an error on an individual input but on a group.
For instance, I have three sort code fields for a bank details form.. they're all required, but I don't want each one individually to get an error message (as they're inline), if any of them error, I want the group to get the error message and error class.
Is this possible without writing custom javascript to parse the form data manually?
You can't do that with data-parsley-group. Groups were created in order to validate a multi-step form. That is norrmally a large form that you split into steps (groups) and validate them one at a time.
What you can use, without adding custom javascript, is data-parsley-errors-container.
You should apply this attribute on every field where you want to group the error messages. You should use something like this:
data-parsley-errors-container="#element"
Where element is the id of the element where the messages will be displayed.
Here is an example on how you should create your form (jsfiddle available):
<form class="form-inline" role="form" id="myForm">
<div class="form-group col-xs-12">
<input type="text" class="form-control col-xs-3" id="field1" required
placeholder="Field 1" data-parsley-errors-container="#listFieldError" />
<input type="text" class="form-control col-xs-3" id="field2" required
placeholder="Field 2" data-parsley-errors-container="#listFieldError" />
<input type="text" class="form-control col-xs-3" id="field3" required
placeholder="Field 3" data-parsley-errors-container="#listFieldError" />
</div>
<div class="form-group">
<div id="listFieldError"></div>
<button type="submit" class="btn btn-default">Sign in</button>
</div>
</form>

Categories