Properties not getting value in ngOnIt() in Angular 11 - angular-material

I am getting the data from the database using an Api which is in the LeaveService. To get the data the method used is applyLeaveGet(id:string) which is in LeaveService. This method provides certain values like the joiningDate from the database.
I am using Angular Material UI with reactive form.
The issue is that even though the leave instance is getting the data, but the in ngOnInt(), the properties are not getting the values.ngOnInt() does get triggred. For example I get the error undefined for joining date.
How can I solve the issue. Thank you for the help
LeaveService : applyLeaveGet(id:string) method
applyLeaveGet(id:string){
return this.http.get<Leave>('https://localhost:44330/api/leave/ApplyLeaveGet/'+ id);
}
ApplyLeave Component
import { HttpClient } from '#angular/common/http';
import { Component, OnInit } from '#angular/core';
import { FormBuilder, FormControl, FormGroup} from '#angular/forms';
import { ActivatedRoute } from '#angular/router';
import { AuthenticationService } from 'src/app/authentication.service';
import { Leave } from '../interfaces/leave';
import { LeaveService } from '../services/leave.service';
#Component({
selector: 'app-add-edit-leave',
templateUrl: './add-edit-leave.component.html',
styleUrls: ['./add-edit-leave.component.css']
})
export class AddEditLeaveComponent implements OnInit {
form: FormGroup;
currentDate = new Date();
minDate: Date;
maxDate: Date;
selectedFile: File = null;
url : any;
leave :Leave;
constructor(private fb: FormBuilder, private http: HttpClient
,private leaveService : LeaveService
,private route : ActivatedRoute
,private authenticationService: AuthenticationService
) {
leaveService.applyLeaveGet(authenticationService.getUserId())
.subscribe(data =>
this.leave = data
);
// Set the minimum to January 1st 20 years in the past and December 31st a year in the future.
const currentYear = new Date().getFullYear();
this.minDate = new Date(currentYear - 20, 0, 1);
this.maxDate = new Date(currentYear + 1, 11, 31);
}
ngOnInit() {
this.form = this.fb.group({
"currentDate": new FormControl(this.currentDate.toISOString().split("T")[0]),
"joiningDate":[''],
"fromDate":[''],
"tillDate":[''],
"leaveType":[''],
"duration":[''],
"reason":[''],
"filePath":['']
});
}
onSelectFile(event: any) {
this.selectedFile = <File>event.target.files[0];
if (event.target.files && event.target.files[0]) {
var reader = new FileReader();
reader.onload = (event: any) => {
this.url = event.target.result;
}
reader.readAsDataURL(event.target.files[0]);
}
else
{
this.url = "";
}
}
onSubmit(){
var userId = this.authenticationService.getUserId();
const formData = new FormData();
formData.append('userId', userId);
formData.append('currentDate', this.form.value.fullName);
formData.append('joiningDate', this.form.value.fullName);
formData.append('fromDate', this.form.value.fullName);
formData.append('tillDate', this.form.value.fullName);
formData.append('leaveType', this.form.value.fullName);
formData.append('duration', this.form.value.fullName);
formData.append('reason', this.form.value.fullName);
formData.append('balanceAnnualLeave', this.form.value.fullName);
formData.append('balanceSickLeave', this.form.value.fullName);
formData.append('balanceAnnualLeave', this.form.value.fullName);
formData.append('File', this.selectedFile);
}
}
this is the html
<p>add-edit-leave works!</p>
<div class="container">
<form class="form-container" [formGroup]="form" (ngSubmit)="onSubmit()">
<mat-card>
<mat-card-header>
<mat-card-title>Apply Leave</mat-card-title>
</mat-card-header>
<mat-card-content>
<div class="row">
<div class="col-md-6">
<mat-form-field class="full-width">
<mat-label>Today's Date</mat-label>
<input formControlName="currentDate" type="date" class="form-control" matInput placeholder="Today's Date" readonly >
</mat-form-field>
</div>
<div class="col-md-6">
<mat-form-field class="full-width">
<mat-label>Joining Date</mat-label>
<input formControlName="joiningDate" type="datetime" class="form-control" matInput placeholder="Joining Date">
</mat-form-field>
</div>
</div>
<!--Date Requested For-->
<div class="row">
<div class="col-md-6">
<mat-form-field class="full-width" appearance="fill">
<mat-label>From Date</mat-label>
<input matInput formControlName="fromDate" [min]="minDate" [max]="maxDate"
[matDatepicker]="picker">
<mat-datepicker-toggle matSuffix [for]="picker"></mat-datepicker-toggle>
<mat-datepicker #picker></mat-datepicker>
</mat-form-field>
</div>
<div class="col-md-6">
<mat-form-field class="full-width" appearance="fill">
<mat-label>Till Date</mat-label>
<input matInput formControlName="tillDate" [min]="minDate" [max]="maxDate"
[matDatepicker]="pickerTillDate">
<mat-datepicker-toggle matSuffix [for]="pickerTillDate"></mat-datepicker-toggle>
<mat-datepicker #pickerTillDate></mat-datepicker>
</mat-form-field>
</div>
</div>
<!--Leave Type Duration(dropdown box)-->
<div class="row">
<div class="col-md-6">
<mat-form-field class="full-width" appearance="fill">
<mat-label>Leave Type</mat-label>
<select formControlName="leaveType" matNativeControl id="mySelectId">
<option value="" disabled selected></option>
<option value="Annual Leave">Annual Leave</option>
<option value="Sick Leave">Sick Leave</option>
</select>
</mat-form-field>
</div>
<div class="col-md-6">
<mat-form-field class="full-width" appearance="fill">
<mat-label>Duration</mat-label>
<select formControlName="duration" matNativeControl id="mySelectId">
<option value="" disabled selected></option>
<option value="Full Day ">Full Day</option>
<option value="First Half Day">First Half Day</option>
<option value="Second Half Day">Second Half Day</option>
</select>
</mat-form-field>
</div>
</div>
<!--Reason-->
<div class="row">
<div class="col-md-12">
<mat-form-field class="full-width">
<mat-label>Reason</mat-label>
<input formControlName="reason" matInput placeholder="Reason">
</mat-form-field>
</div>
</div>
<div class="row">
<div class="col-md-6">
<mat-label>Leave Balacne</mat-label><br>
<ul>
<li>
annualLeaveBalacne: <span>{{leave.balanceAnnualLeave}}</span> <br>
</li>
<li>
sickLeaveBalance: <span>{{leave.balanceSickLeave}}</span>
</li>
</ul>
</div>
</div>
<!--Submit-->
<mat-card-actions>
<button mat-stroked-button type="submit>Basic</button>
</mat-card-actions>
</mat-card-content>
</mat-card>
</form>
</div>

In the current version of your question it does not look like you are any setting values from this.leave in the form in OnInit. From your problem description and the rest of your code I think your problem is the asynchronous call of LeaveService in the constructor. As it it asynchronous code it might not be finished before ngOnInit is called and executed, thus the error messages about undefined values. You have to wait untill the HTTP call is finished before accessing the data.
As you should not perform potentially long running HTTP calls in the constructor, I suggest moving that part in OnInit. Everything that's not long running and asynchronous can be performed in the constructor. Your code could be refactored like this:
constructor(private fb: FormBuilder,
private http: HttpClient,
private leaveService : LeaveService,
private route : ActivatedRoute,
private authenticationService: AuthenticationService
) {
// Set the minimum to January 1st 20 years in the past and December 31st a year in the future.
const currentYear = new Date().getFullYear();
this.minDate = new Date(currentYear - 20, 0, 1);
this.maxDate = new Date(currentYear + 1, 11, 31);
this.form = this.fb.group({
"currentDate": new FormControl(this.currentDate.toISOString().split("T")[0]),
"joiningDate": [''],
"fromDate": [''],
"tillDate": [''],
"leaveType": [''],
"duration": [''],
"reason": [''],
"filePath": ['']
});
}
ngOnInit() {
leaveService.applyLeaveGet(authenticationService.getUserId())
.subscribe(data =>
{
this.leave = data;
// now data is here and can be used to set initial form values, example:
this.form.get('leaveType').setValue(this.leave.Type);
}
);
}

Related

Loading partialView through ajax not working

i am trying to show order Summary through partial View and ajax.Request is going to server but my action method of Showsummary never hits. i want to summary of order through partial view.
[HttpPost]
public PartialViewResult Showsummary(OrderViewModel model)
{
try
{
var p = model.Packages.SelectMany(x => x.Packages).Select(y => new OrderPackagesViewModel()
{
PkgName = y.PkgName,
pkg_Id = y.id,
Ser_Id = y.Ser_Id,
Quantity = y.Quantity,
price = (y.TotalPrice - (y.DiscountPercent / 100 * y.TotalPrice)) * y.Quantity
}).ToList();
model.OrderPackages = p;
return PartialView("OrderSummary", model);
}
catch
{
return PartialView("OrderSummary", model);
}
}
My Ajax
$("#summary").click(function () {
console.log("calling summary");
event.preventDefault();
$.ajax({
type: "POST",
url: "/Order/Showsummary",
data: $("form.signup-form").serialize(),
success: function (data) {
console.log(data)
$('#page_2').hide();
$('#page_3').show();
$('#page_3').html(data);
},
failure: function (response) {
console.log(response.responseText);
},
error: function (response) {
console.log(response.responseText);
}
});
})
//Html Code
<div id="page_1">
<input asp-for="cus_name" placeholder="First Name" >
<input asp-for="Email" placeholder="Email" >
<select asp-for="Country" class="ui search dropdown">
<option value="">Select Country</option>
<option value="AF">Afghanistan</option>
<option value="AX">Åland Islands</option>
</select>
<input asp-for="cus_phone" placeholder="Phone Number"/>
<select asp-for="FirstPreferences" class="custom-select mr-sm-2"
asp-items="#(newSelectList(Preferences))">
<option value="">Select</option>
</select>
<select asp-for="FirstPreferedTimeStart" class="menu">
<option value="">HH:MM</option>
<option value="00:00:00">00:00</option>
<option value="01:00:00">01:00</option>
</select>
<textarea asp-for="Message" class="form-control"> </textarea>
</div>
//Page2 details of packages available. It is list of GroupByServices which contain fields ser_id Ser_Name and List of ServicePackages.
<div id="page_2" style="display:none">
<div>
<h1 id="heading">Choose a Package!</h1>
</div>
<div class="buttons">
#foreach (var services in Model.Packages)
{
<a href="#service_#services.Ser_Id"><div class="logo-p">
<h2>#services.Ser_Name</h2></div></a>
}
</div>
<!-- packages -->
#for (int i = 0; i < Model.Packages.Count; i++)
{
<div class="packages" id="service_#Model.Packages[i].Ser_Id">
<h1 id="custom-website-design">
#Model.Packages[i].Ser_Name
</h1>
<div class="packs-content">
#for (int j = 0; j < Model.Packages[i].Packages.Count(); j++)
{
<div class="pack1">
<div class="pack-price">
<div>
<input asp-for="#Model.Packages[i].Packages[j].id" hidden />
<input asp-for="#Model.Packages[i].Packages[j].PkgName" hidden />
<input asp-for="#Model.Packages[i].Packages[j].Ser_Id" hidden />
<input asp-for="#Model.Packages[i].Packages[j].Ser_Name" hidden />
<h1>#Model.Packages[i].Packages[j].PkgName</h1>
<p>#Model.Packages[i].Packages[j].Ser_Name PACKAGE</p>
</div>
<p>$#Model.Packages[i].Packages[j].TotalPrice</p>
<input asp-for="#Model.Packages[i].Packages[j].TotalPrice" hidden />
</div>
<div class="pack-features">
<div class=""></div>
#foreach (var features in Model.Packages[i].Packages[j].Description)
{
<h2>#features</h2>
}
</div>
<div class="pack-order">
<div class="row-1">
#{
double discount = (Model.Packages[i].Packages[j].DiscountPercent / 100 * Model.Packages[i].Packages[j].TotalPrice);
double PriceAfterDiscount = Model.Packages[i].Packages[j].TotalPrice - discount;
}
<p>SPECIAL DISCOUNT</p>
<P>-$#discount</P>
</div>
<div class="row-2">
<p>FINAL PRICE FOR LIMITED TIME</p>
</div>
<div class="row-3">
<a asp-controller="Packages" asp-action="Detail" asp-route-id="#Model.Packages[i].Packages[j].id" target="_blank">view details</a>
<h1>$#PriceAfterDiscount</h1>
<input asp-for="#Model.Packages[i].Packages[j].DiscountPercent" hidden />
</div>
<div class="row-4">
<h4>Add To Buying List</h4>
<div class="input-group mb-3 order-btn-pack">
<div class="input-group-prepend">
<div class="input-group-text">
<input asp-for="#Model.Packages[i].Packages[j].is_selected" aria-label="Checkbox for following text input">
</div>
</div>
<input asp-for="#Model.Packages[i].Packages[j].Quantity" value="1" min="1" required placeholder="Quantity" class="form-control" aria-label="Text input with checkbox">
</div>
</div>
<div class="row-5">
<p>Discuss this offer with expert</p>
<div class="discuss">
<p>12345467889</p>
<p id="chat-btn_10">Live Chat</p>
</div>
</div>
</div>
</div>
}
<input asp-for="HoldPackage" hidden/>
</div>
</div>
}
<div>
<button type="button" class="btn btn-danger px-2 btn-lg" onclick="PageBack(this.parentElement.parentElement)">Back</button>
<button type="button" class="btn btn-danger px-2 btn-lg" id="summary">Summary!</button>
</div>
</div>
Edit!!!!
i have changed this line in ajax now it start hitting my controller action but still all form values are empty seems model binding is unable to recognize my fields
**const model= $("form").serialize()**
console.log(model); //data is there thats fine
and in ajax
data: { model },
my model have field called packages which is list of some fields and inside it there is one another list.
One thing is clear. $("form").serialize() is not working in my case its giving me 415 Unsupported Media Type client error response. I think problem is due to nested List
I have checked your code on my side with a simple OrderViewModel object, it works well. I suggest you could try to add '[FromBody]' in the action method, Like this:
....
Edit
According your description, it seems that you are using the Nested List and meet 415 error when using the [FromBody]. I have modified the sample code, in the action method, it's not using the [FromBody] attribute and in the JQuery Ajax method, there is no need to use the JSON.stringify method to change the JavaScript object. More detail information, please check the following code:
Model Class (Suppose the OrderViewModel contain a List):
public class OrderViewModel
{
public int OrderId { get; set; }
public string OrderName { get; set; }
public List<Package> Packages { get; set; }
}
public class Package
{
public int Pid { get; set; }
public string PackageTitle { get; set; }
}
Code in the Controller:
/// <summary>
/// //display the order
/// </summary>
/// <returns></returns>
public IActionResult ShowOrder()
{
OrderViewModel ovm = new OrderViewModel()
{
OrderId = 1001,
OrderName = "order 1",
Packages = new List<Package>()
{
new Package(){ Pid=101, PackageTitle="first Package"},
new Package(){ Pid=102, PackageTitle="second package"}
}
};
return View(ovm);
}
/// <summary>
/// JQuery ajax post method
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
[HttpPost]
public PartialViewResult Showsummary(OrderViewModel model)
{
try
{
//...
return PartialView("OrderSummary", model);
}
catch
{
return PartialView("OrderSummary", model);
}
}
ShowOrder.cshtml:
#model MVCSample.Models.OrderViewModel
#{
ViewData["Title"] = "ShowOrder";
}
<div class="row">
<div class="col-md-4">
<form asp-action="Showsummary" asp-controller="Home" method="post" class="signup-form">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="OrderId" class="control-label"></label>
<input asp-for="OrderId" class="form-control" />
<span asp-validation-for="OrderId" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="OrderName" class="control-label"></label>
<input asp-for="OrderName" class="form-control" />
<span asp-validation-for="OrderName" class="text-danger"></span>
</div>
<div id="packages">
#for (int i = 0; i < Model.Packages.Count; i++)
{
<div class="form-group">
<label asp-for="#Model.Packages[i].Pid" class="control-label"></label>
<input asp-for="#Model.Packages[i].Pid" class="form-control" />
<span asp-validation-for="#Model.Packages[i].Pid" class="text-danger"></span>
<br />
<label asp-for="#Model.Packages[i].PackageTitle" class="control-label"></label>
<input asp-for="#Model.Packages[i].PackageTitle" class="form-control" />
<span asp-validation-for="#Model.Packages[i].PackageTitle" class="text-danger"></span>
</div>
}
</div>
#*<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
</div>*#
</form>
</div>
</div>
<div>
<input type="button" id="summary" value="Summary" />
<div id="page_3">
</div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script>
$(function () {
$("#summary").click(function () {
console.log("calling summary");
event.preventDefault();
//create a object to store the entered value.
var OrderViewModel = {};
//using jquery to get the entered value.
OrderViewModel.OrderId = $("input[name='OrderId']").val();
OrderViewModel.OrderName = $("input[name='OrderName']").val();
var packages = [];
//var count = $("#packages>.form-group").length; //you could use it to check the package count
$("#packages>.form-group").each(function (index, item) {
var package = {}
package.Pid = $(item).find("input[name='Packages[" + index + "].Pid']").val();
package.PackageTitle = $(item).find("input[name='Packages[" + index + "].PackageTitle']").val();
packages.push(package);
});
OrderViewModel.Packages = packages;
$.ajax({
type: "POST",
url: "/Home/Showsummary", //remember change the controller to your owns.
data: OrderViewModel,
success: function (data) {
console.log(data)
$('#page_3').html(data);
},
failure: function (response) {
console.log(response.responseText);
},
error: function (response) {
console.log(response.responseText);
}
});
});
});
</script>
Then the output as below:
Edit:
Besides, I also found that by using the above sample, if I just change the data: OrderViewModel to data: $("form.signup-form").serialize() (in the Ajax method), I could also get the OrderViewModel and the Packages in the action method.

Angular 2 HTML template in Visual studio 2015

I am working on an Angular 2 dashboard in Visual studio 2015, MVC project. I downloaded a sample dashboard and using it as reference.
login.component.ts
import {Component} from '#angular/core';
import {FormGroup, AbstractControl, FormBuilder, Validators} from '#angular/forms';
#Component({
selector: 'login',
templateUrl: './login.html',
styleUrls: ['./login.scss']
})
export class Login {
public form:FormGroup;
public email:AbstractControl;
public password:AbstractControl;
public submitted:boolean = false;
constructor(fb:FormBuilder) {
this.form = fb.group({
'email': ['', Validators.compose([Validators.required, Validators.minLength(4)])],
'password': ['', Validators.compose([Validators.required, Validators.minLength(4)])]
});
this.email = this.form.controls['email'];
this.password = this.form.controls['password'];
}
public onSubmit(values:Object):void {
this.submitted = true;
if (this.form.valid) {
// your code goes here
// console.log(values);
}
}
}
In that reference dashboard, they have used login.html template, in which the label values are referenced as {{'login.title'}}, {{'login.signup_link'}},{{'login.email'}}, {{'login.password'}} etc. I don't understand from where there are getting this label values.
login.html
<div class="auth-main">
<div class="auth-block">
<h1 translate>{{'login.title'}}</h1>
<a routerLink="/register" class="auth-link" translate>{{'login.signup_link'}}</a>
<form [formGroup]="form" (ngSubmit)="onSubmit(form.value)" class="form-horizontal">
<div class="form-group row" [ngClass]="{'has-error': (!email.valid && email.touched), 'has-success': (email.valid && email.touched)}">
<label for="inputEmail3" class="col-sm-2 control-label" translate>{{'login.email'}}</label>
<div class="col-sm-10">
<input [formControl]="email" type="email" class="form-control" id="inputEmail3" placeholder="{{'login.email' | translate}}">
</div>
</div>
<div class="form-group row" [ngClass]="{'has-error': (!password.valid && password.touched), 'has-success': (password.valid && password.touched)}">
<label for="inputPassword3" class="col-sm-2 control-label" translate>{{'login.password'}}</label>
<div class="col-sm-10">
<input [formControl]="password" type="password" class="form-control" id="inputPassword3" placeholder="{{'login.password' | translate}}">
</div>
</div>
<div class="form-group row">
<div class="offset-sm-2 col-sm-10">
<button [disabled]="!form.valid" type="submit" class="btn btn-default btn-auth" translate>{{'login.sign_in'}}</button>
<a routerLink="/login" class="forgot-pass" translate>{{'login.forgot_password'}}</a>
</div>
</div>
</form>
<div class="auth-sep"><span><span translate>{{'login.sign_from_app_text'}}</span></span></div>
<div class="al-share-auth">
<ul class="al-share clearfix">
<li><i class="socicon socicon-facebook" title="{{'login.share_on_facebook' | translate}}"></i></li>
<li><i class="socicon socicon-twitter" title="{{'login.share_on_twitter' | translate}}"></i></li>
<li><i class="socicon socicon-google" title="{{'login.share_on_google_plus' | translate}}"></i></li>
</ul>
</div>
</div>
</div>

Form validation on non form field angular2

im quite new with angular2, but i seem to manage ok for a beginner. However, i'm stuck on some validation issues. i want to validate a component that is not a form field (e.g. input, select e.t.c).
I'm using a bootstrap dropdown which uses an unsorted list.
dropdownButtons.html
<div class="btn-group" dropdown>
<button type="button" class="btn btn-default" dropdownToggle >
{{ selected ? selected : 'Type...'}}
</button>
<ul class="dropdown-menu" dropdownMenu>
<li *ngFor="let value of values;let i = index" (click)="onChange(value)">
{{value.label}}
</li>
</ul>
</div>
dropdownButtons.component.ts
import {Component, EventEmitter, Output, Input, Injectable} from '#angular/core';
import { DROPDOWN_DIRECTIVES } from 'ng2-bootstrap/ng2-bootstrap';
#Component({
selector: 'dropdown-buttons',
template: require('./dropdownButtons.html'),
directives: [DROPDOWN_DIRECTIVES]
})
#Injectable()
export class DropdownButtons {
#Input()
values: DropdownValue[] = [{ "value": "RSS", "label": "RSS" },{ "value": "REST", "label": "REST" }];
#Input()
selected : string;
#Output()
select: EventEmitter<DropdownValue>;
constructor() {
this.select = new EventEmitter();
}
onChange(type) {
this.select.emit(type);
}
}
export class DropdownValue {
value:string;
label:string;
constructor(value:string,label:string) {
this.value = value;
this.label = label;
}
}
My form looks like this.
<form (ngSubmit)="onSubmit()" #refererform="ngForm">
<div class="form-group">
<label for="inputUrl">Url</label>
<input type="text" class="form-control" id="inputUrl" placeholder="Url" required
[(ngModel)]="model.url" name="url">
</div>
<div class="form-group">
<dropdown-buttons [(selected)]="model.type" (select)="onSelect($event)" ></dropdown-buttons>
</div>
<div class="form-group" ng-show="showDetails" *ngIf="isShown()">
<label for="header">Header</label>
<textarea placeholder="Default Input" class="form-control" id="header"
[(ngModel)]="model.header" name="header"></textarea>
</div>
<div class="form-group" ng-show="showDetails" *ngIf="isShown()">
<label for="payload">Payload</label>
<textarea placeholder="Default Input" class="form-control" id="payload"
[(ngModel)]="model.payload" name="payload"></textarea>
</div>
<button type="submit" class="btn btn-danger" >Submit</button>
</form>
I tried to use ngModel (using required in the tags) and the FormGroup option, where i define some formcontrols. It works fine with form controls, but i can't seem to figure out how i validate non form components, is it even possible?
thanks in advance.

How to bind ngFormModel in angular2 using Dart?

The following works in a form (the form is displayed)
.html
<form (ngSubmit) = "onSubmit()"
#nameForm = "ngForm">
{{diagnostic}}
<div class = "mdl-card mdl-shadow--3dp layout horizontal wrap">
<div class = "mdl-card__title">
<h2 class = "mdl-card__title-text">Name</h2>
</div>
<div
class = "mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
<input
required
type = "text"
[(ngModel)] = "name.first"
ngControl = "first"
#first = "ngForm"
(input)="onInputHandler($event)"
class = "mdl-textfield__input ng-valid"
id = "first">
<label
class = "mdl-textfield__label"
for = "first">First</label>
<span [hidden] = "isFirstValid"
class = "mdl-textfield__error">{{firstErrorMsg}}</span>
</div>
<div class =
"mdl-card__actions mdl-card--border">
<button id = "startButton"
class = "mdl-button mdl-js-button mdl-button--raised mdl-button--accent mdl-js-ripple-effect"
>Submit
</button>
<br>
<button class = "mdl-button mdl-js-button mdl-button--raised mdl-button--colored">
Button All
</button>
</form>
Trying to follow the example at Forms and Validation in Angular 2.0,
I cannot get the UI to display by changing the first line of the form to
<form (ngSubmit) = "onSubmit()"
[ngFormModel]="form" #f="form">
{{diagnostic}}
..
With the change the browser simply does not display anything as if it cannot parse the markup - the error is actually shown in pub-serve or debug mode.
Transform TemplateCompiler on epimss_ng2_reg|lib/components/name_component.ng_meta.json threw error: Template parse errors:
There is no directive with "exportAs" set to "form" ("
<div [hidden] = "isSubmitted">
<form (ngSubmit) = "onSubmit()"
[ng-form-model]="form" [ERROR ->]#f="form">
{{diagnostic}}
<div class = "mdl-card mdl-shadow--3dp layout horizontal wrap">
"): NameComponent#12:31
....
Why is this not working?
Seems this was changed since when the blog post was created.
NgForm is now exported as ngForm instead of form.
[ngFormModel]="form" #f="ngForm">
It's correct in the GitHub source but not in the blog post.
Full component according to the example in the blog post in Dart
#Component(selector: 'form-element')
#View(template: '''
<h1>form-element</h1>
<form (ngSubmit)="onSubmit()" [ngFormModel]="form" #f="ngForm">
<div>
<div class="formHeading">First Name</div>
<input type="text" id="firstName" ngControl="firstName">
<div class="errorMessage" *ngIf="f.form.controls['firstName'].touched && !f.form.controls['firstName'].valid">First Name is required</div>
</div>
<div>
<div class="formHeading">Street Address</div>
<input type="text" id="firstName" ngControl="streetAddress">
<div class="errorMessage" *ngIf="f.form.controls['streetAddress'].touched && !f.form.controls['streetAddress'].valid">Street Address is required</div>
</div>
<div>
<div class="formHeading">Zip Code</div>
<input type="text" id="zip" ngControl="zip">
<div class="errorMessage" *ngIf="f.form.controls['zip'].touched && !f.form.controls['zip'].valid">Zip code has to be 5 digits long</div>
</div>
<div>
<div class="formHeading">Address Type</div>
<select id="type" ngControl="type">
<option [value]="'home'">Home Address</option>
<option [value]="'billing'">Billing Address</option>
</select>
</div>
<button type="submit" [disabled]="!f.form.valid">Save</button>
<div>
<div>The form contains the following values</div>
<div>
{{payLoad}}
</div>
</div>
</form>
''')
class FormElement {
ControlGroup form;
String payLoad;
FormElement(FormBuilder fb) {
form = fb.group({
"firstName": ['', Validators.required],
"streetAddress": ['', Validators.required],
"zip": [
'',
Validators.compose([ZipValidator.validate])
],
"type": ['home']
});
}
void onSubmit() {
payLoad = JSON.encode(this.form.value);
}
}

Can't seem to get AngularFire '$update' working

I’m pretty new to Angular, Firebase and AngularFire, so it's probable I'm going about this the wrong way.
Basically I have a form in a modal(UI Bootstrap) and I want to update some previously stored values, but AngularFire ‘$update’ doesn’t update them in Firebase. Creating and deleting items outside the modal is working fine.
This is within my service:
updateItem: function (id, item) {
var item_ref = new Firebase(FIREBASE_URL + ‘/items/‘ + user_id + '/' + id);
var item = $firebase(item_ref);
item.$update({
name: item.name,
notes: item.notes
});
}
This is within my controller:
$scope.edit = function(id) {
$modal.open({
templateUrl: 'views/item.html',
backdrop: 'static',
keyboard: false,
resolve: {
data: function() {
return {
title: 'Edit item',
item: Items.getItem(id)
};
}
},
controller: 'EditItemCtrl'
})
.result.then(function(item) {
Items.updateItem(item.$id, item);
});
};
This is my modal controller:
app.controller('EditItemCtrl', function ($scope, $modalInstance, data) {
$scope.data = data;
$scope.ok = function(item) {
$modalInstance.close(item);
};
$scope.cancel = function() {
$modalInstance.dismiss();
};
});
This is my modal template:
<div class="modal-content">
<div class="modal-header">
<button class="close" style="margin-top: -10px;" type="button" ng-click="cancel()">×</button>
<h3>{{data.title}}</h3>
</div>
<div class="modal-body">
<form name="editItem" role="form" novalidate>
<div class="form-group">
<label class="sr-only" for="itemName">Item name</label>
<input name="name" type="text" class="form-control" placeholder="Item name" value="{{data.item.name}}" ng-model="data.item.name">
</div>
<div class="form-group">
<label class="sr-only" for="itemNotes">Item notes</label>
<textarea name="notes" class="form-control" rows="2" id="itemNotes" placeholder="Notes" ng-model="data.item.notes" ng-maxlength="500">{{data.item.notes}}</textarea>
</div>
</form>
</div>
<div class="modal-footer">
<button class="btn btn-default" type="button" ng-click="cancel()">Cancel</button>
<button class="btn btn-primary" type="button" ng-click="ok(editItem.data.item)">OK</button>
</div>
</div>
Stepping through everything shows that the item to be updated and new values are being passed through to the service, but they're not making their way into Firebase.
I'm guessing that I'm probably going about this the wrong way though - any guidance would be much appreciated.

Resources