Skip to content

Instantly share code, notes, and snippets.

@sod

sod/component.ts Secret

Created August 15, 2016 11:47
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sod/049ce1f29f6c6d83bcfdd99ecef49513 to your computer and use it in GitHub Desktop.
Save sod/049ce1f29f6c6d83bcfdd99ecef49513 to your computer and use it in GitHub Desktop.
import {Component, OnDestroy, Input, ApplicationRef} from '@angular/core';
import {Subject} from 'rxjs/Subject';
import {ProceedButtonState} from '../state/proceed-button-state';
import {ObservablePending} from '../../main/class/observable-pending';
import {ObservableHandler} from '../../main/class/observable-handler';
import {ErrorState} from '../../main/state/error-state';
import {CheckoutNavigationService} from '../service/checkout-navigation-service';
import {Address} from '../model/address';
import {AddressDefaultFormType} from './address-default-form-type';
import {AddressPackstationFormType} from './address-packstation-form-type';
import {FormType} from '../../core/form/form-type';
import {UserRepository} from '../repository/user-repository';
import {AddressDto} from '../model/address-dto';
import {CheckoutAddressState} from '../state/checkout-address-state';
import {AddressErrorsMapper} from '../mapper/address-errors-mapper';
import {FormErrorResponse} from '../model/form-error-response';
import {Error} from '../../core/model/error';
@Component({
selector: 'address-form',
template: `
<form class="ry-form-address" *ngIf="type" [class.has-error-highlight]="errorState.highlight" (submit)="submit()" [formGroup]="type.form">
<div class="form-group ry-checkout-address__checkbox-deliver-to-packstation" *ngIf="kind === 'shipping'">
<fancy-checkbox [checked]="type.isPackstationType" (checkedChange)="switchFormType()">
{{ 'x.address.deliver_to_packstation'|trans }}
</fancy-checkbox>
</div>
<div class="row">
<div class="col-xs-6" [class.has-error]="type|ryHasError:'firstName'">
<fancy-input [tabindex]="1"
[label]="'x.address.first_name'|trans"
formControlName="firstName">
</fancy-input>
</div>
<div class="col-xs-6" [class.has-error]="type|ryHasError:'lastName'">
<fancy-input [tabindex]="1"
[label]="'x.address.last_name'|trans"
formControlName="lastName">
</fancy-input>
</div>
</div>
<div *ngIf="type.form.controls.optional" [class.has-error]="type|ryHasError:'optional'">
<fancy-input [tabindex]="1"
[label]="'x.address.optional'|trans"
formControlName="optional">
</fancy-input>
</div>
<div *ngIf="type.form.controls.postNumber" [class.has-error]="type|ryHasError:'postNumber'">
<fancy-input [tabindex]="1"
type="number"
[label]="'x.address.post_number'|trans"
formControlName="postNumber">
</fancy-input>
</div>
<div *ngIf="type.form.controls.packstationNumber" [class.has-error]="type|ryHasError:'packstationNumber'">
<fancy-input [tabindex]="1"
type="number"
[label]="'x.address.packstation_number'|trans"
formControlName="packstationNumber">
</fancy-input>
</div>
<div *ngIf="type.form.controls.street" class="row">
<div class="col-xxs-12 col-xs-9" [class.has-error]="type|ryHasError:'street'">
<fancy-input [tabindex]="1"
[label]="'x.address.street'|trans"
formControlName="street">
</fancy-input>
</div>
<div class="col-xxs-12 col-xs-3" [class.has-error]="type|ryHasError:'streetNumber'">
<fancy-input [tabindex]="1"
[label]="'x.address.street_number'|trans"
formControlName="streetNumber">
</fancy-input>
</div>
</div>
<div class="row">
<div class="col-xxs-12 col-xs-3" [class.has-error]="type|ryHasError:'zip'">
<fancy-input [tabindex]="1"
[label]="'x.address.zip'|trans"
formControlName="zip">
</fancy-input>
</div>
<div class="col-xxs-12 col-xs-9" [class.has-error]="type|ryHasError:'city'">
<fancy-input [tabindex]="1"
[label]="'x.address.city'|trans"
formControlName="city">
</fancy-input>
</div>
</div>
<div class="form-group ry-fancy-select" [class.has-error]="type|ryHasError:'country'">
<select class="form-control ry-fancy-select__select" tabindex="1" formControlName="country">
<option disabled [ngValue]="null">{{ 'x.address.country'|trans }}</option>
<option *ngFor="let country of type.countries" [ngValue]="country.value">{{ country.label|trans }}</option>
</select>
<label class="ry-fancy-select__label" [class.is-empty]="!type.form.controls.country.value">
{{ 'x.address.country'|trans }}
</label>
</div>
<div class="form-group" [class.has-error]="type|ryHasError:'phone'">
<fancy-input [tabindex]="1"
[label]="'x.address.phone'|trans"
formControlName="phone">
</fancy-input>
</div>
<div role="alert" class="ry-form__message ry-form__message--error" *ngIf="saving?.error">
{{ getSavingError() }}
</div>
<div class="form-group">
<div class="row">
<div class="col-md-5 col-md-offset-7 col-lg-4 col-lg-offset-8 hidden-xs hidden-sm">
<checkout-proceed-button></checkout-proceed-button>
</div>
</div>
</div>
</form>
`
})
export class AddressFormComponent implements OnDestroy {
@Input() public kind: 'billing'|'shipping';
@Input() public addresses: Address[];
public type = new AddressDefaultFormType();
public save = new Subject<AddressDto>();
public saving: ObservablePending<Address>;
constructor(private checkoutNavigationService: CheckoutNavigationService,
private proceedButtonState: ProceedButtonState,
private userRepository: UserRepository,
private applicationRef: ApplicationRef,
private addressState: CheckoutAddressState,
private addressErrorsMapper: AddressErrorsMapper,
public errorState: ErrorState) {
}
public ngOnInit(): void {
ObservableHandler.from<Address>(this.save, this)
.setRetries(0)
.setApi(address => this.userRepository.addAddress(address, this.addressState.getBackendKind(this.kind)))
.onPending(pending => this.saving = pending)
.subscribe(address => {
this.addresses.push(address);
this.addressState.select(address, this.kind, false);
if (this.checkoutNavigationService.canProceed()) {
this.checkoutNavigationService.proceed();
}
});
this.proceedButtonState.register(this, {
click: (event: MouseEvent) => {
event.preventDefault();
this.errorState.setDirty(this.type.form);
this.errorState.doHighlight();
if (this.type.form.valid) {
this.save.next(this.type.getValues());
}
},
disabled: () => this.saving || false,
label: () => 'x.address.save_and_proceed'
});
}
public switchFormType(): void {
const old = this.type;
const Type = this.type instanceof AddressPackstationFormType ? AddressDefaultFormType : AddressPackstationFormType;
this.type = null;
// force view update so old NgForm can destroy
this.applicationRef.tick();
this.type = new Type();
FormType.copyValues(old, this.type);
}
public ngOnDestroy(): void {
}
public getSavingError(): string {
return this.addressErrorsMapper.getError(this.saving.getErrorBody<Error[]|FormErrorResponse>());
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment