File
Implements
Metadata
selector |
app-auto-complete |
styleUrls |
auto-complete.component.css |
templateUrl |
./auto-complete.component.html |
Index
Properties
|
|
Methods
|
|
Inputs
|
|
Outputs
|
|
defaultTemplateId
|
Type: string
|
|
Methods
isToWhoNotValid
|
isToWhoNotValid()
|
|
|
move
|
move(delta: number)
|
|
Parameters :
Name |
Type |
Optional |
delta |
number
|
no
|
|
payToNameChanged
|
payToNameChanged(value: string)
|
|
Parameters :
Name |
Type |
Optional |
value |
string
|
no
|
|
resetAutoCompleteForm
|
resetAutoCompleteForm()
|
|
|
selectedPayment
|
selectedPayment()
|
|
|
showAgainPayment
|
showAgainPayment(template: Template)
|
|
|
showNewPayment
|
showNewPayment()
|
|
|
autocompleteform
|
autocompleteform:
|
Decorators : ViewChild
|
|
hideError
|
hideError:
|
Default value : true
|
|
index
|
index:
|
Default value : -1
|
|
isLoading
|
isLoading:
|
Default value : false
|
|
isLookUp
|
isLookUp:
|
Default value : false
|
|
isNewSelected
|
isNewSelected:
|
Default value : true
|
|
loadingMoreRecipients
|
loadingMoreRecipients:
|
Default value : false
|
|
model
|
model:
|
Default value : new AutoCompleteVm()
|
|
payToName
|
payToName: string
|
Type : string
|
Default value : ''
|
|
recipientslookupctn
|
recipientslookupctn:
|
Decorators : ViewChild
|
|
subscription
|
subscription: Subscription
|
Type : Subscription
|
|
templateFilter
|
templateFilter:
|
Default value : new TemplatesFilterPipe()
|
|
towho
|
towho:
|
Decorators : ViewChild
|
|
import {
Component,
EventEmitter,
Input,
OnChanges,
OnInit,
Output,
SimpleChanges,
ViewChild
} from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { Subscription } from 'rxjs';
import { combineLatest } from 'rxjs/observable/combineLatest';
import { filter } from 'rxjs/operators';
import { Template } from '../../models/template.model';
import { TemplatesFilterPipe } from '../../pipes';
import { TemplateService } from '../../services';
import { AppState } from '../../stores/app-state.store';
import { AutoCompleteVm } from './auto-complete-vm.model';
@Component({
selector: 'app-auto-complete',
templateUrl: './auto-complete.component.html',
styleUrls: ['./auto-complete.component.css']
})
export class AutoCompleteComponent implements OnInit, OnChanges {
@Output() create = new EventEmitter();
@Output() pay = new EventEmitter();
@Output() payAgain = new EventEmitter();
@Output() update = Template;
@Input() defaultTemplateId: string;
@ViewChild('toWho') towho;
@ViewChild('userFormToWho') autocompleteform;
@ViewChild('recipientsLookupCtn') recipientslookupctn;
isLoading = false;
payToName = '';
filterValue: string;
model = new AutoCompleteVm();
isLookUp = false;
loadingMoreRecipients = false;
index = -1;
isNewSelected = true;
hideError = true;
templateFilter = new TemplatesFilterPipe();
subscription: Subscription;
constructor(
private templateService: TemplateService,
private app: AppState,
private route: ActivatedRoute
) {}
ngOnInit() {
this.isLoading = true;
this.subscription = combineLatest(this.route.params, this.templateService.templates$)
.pipe(
filter(
([params, templates]) =>
params !== null && params !== undefined && templates !== null && templates !== undefined
)
)
.subscribe(([params, templates]) => {
const selectedTemplateId = params['id'];
if (!templates) {
return;
}
this.model.setTemplates(templates);
this.model.selectedTemplate = templates
.filter(t => t.id === selectedTemplateId)
.reduce((p, c) => c, null);
this.isLoading = false;
if (!this.model.selectedTemplate) {
return;
}
this.showAgainPayment(this.model.selectedTemplate);
});
console.log('app-auto-complete content loaded');
}
ngOnChanges(changes: SimpleChanges) {
if (changes['defaultTemplateId']) {
const id = changes['defaultTemplateId'].currentValue;
if (id) {
this.model.selectedId = id;
}
}
}
showNewPayment() {
const template = this.app.template ? this.app.template : new Template();
template.name = this.payToName;
this.app.template = template;
this.pay.emit();
this.isLookUp = false;
this.hideError = this.payToName.length < 2 ? false : true;
if (!this.hideError) {
return;
}
}
showAgainPayment(template: Template) {
if (!template.id) {
return;
}
this.app.template = template;
this.payToName = template.name;
this.payAgain.emit(template);
this.isLookUp = false;
}
showLookUp() {
this.isLookUp = true;
}
hideLookUp() {
setTimeout(() => {
this.isLookUp = false;
if (!this.app.template) {
return this.showNewPayment();
}
}, 200);
}
resetAutoCompleteForm() {
this.autocompleteform.reset();
}
isToWhoNotValid() {
return this.towho.valid || this.towho.pristine || (this.towho.untouched && this.towho.invalid);
}
selectedPayment() {
if (this.isNewSelected) {
this.showNewPayment();
return;
}
const template = this.model.templates[this.index];
if (template !== null && template !== undefined) {
this.showAgainPayment(template);
}
}
move(delta: number) {
const templates = this.templateFilter.transform(this.model.templates, this.payToName);
const lastIndex = templates.length - 1;
this.index = this.index + delta;
// check for leftmost array boundry
// if beyond the boundry loop index to the end of the array
this.index = this.index < -1 ? lastIndex : this.index;
// check for rightmost array boundry
// if beyond the boundry loop the index to the start of the array
this.index = this.index === templates.length ? -1 : this.index;
if (this.index === -1 && delta === -1) {
// moving up with the keyboard key
this.isNewSelected = true;
if (lastIndex >= 0) {
templates[this.index - delta].selected = false;
}
} else if (this.index === -1 && delta === 1) {
// loop forward to the item on the list from the bottom using (downArrow key)
this.isNewSelected = true;
if (lastIndex >= 0) {
templates[lastIndex].selected = false;
}
this.recipientslookupctn.nativeElement.scrollTop = 0; // controll scrollUp navigation
} else if (this.index === lastIndex && delta === -1) {
// loop back to the last index(item on the list) using (upArrow key)
this.isNewSelected = false;
templates[this.index].selected = true;
this.recipientslookupctn.nativeElement.scrollTop += 9999999; // controll scrollDown navigation
} else if (this.index === 0 && delta === 1) {
// moving down with the keyboard key
this.isNewSelected = false;
templates[this.index].selected = true;
} else if (this.index === -2) {
this.isNewSelected = false;
templates[lastIndex].selected = true;
} else {
// using the filtering while using the up and down controls
templates[this.index - delta].selected = false;
templates[this.index].selected = true; // highlights templates unto movement
}
}
scrollDown() {
this.recipientslookupctn.nativeElement.scrollTop += 45;
}
scrollUp() {
this.recipientslookupctn.nativeElement.scrollTop += -45;
}
payToNameChanged(value: string) {
// clearing the index to allow filtering while using the movement controls
this.model.templates.forEach(template => {
// resets the hover state upon filtering or index change
template.selected = false;
});
this.isNewSelected = true;
this.payToName = value;
this.index = -1;
this.app.template = null;
}
}
<form #userFormToWho="ngForm">
<p>To whom do you want to send money?</p>
<div [hidden]="isToWhoNotValid() && hideError" class="alert alert-danger alert-towho">
We need a name to send the money
</div>
<div id="toWhoCtn">
<input
type="text"
id="toWho"
#toWho="ngModel"
name="recipient"
tabindex="3"
pattern=".{2,}"
placeholder="Name or Nickname"
autocomplete="off"
required
[ngModel]="payToName"
(ngModelChange)="payToNameChanged($event)"
(focus)="showLookUp()"
(keydown.ArrowDown)="scrollDown()"
(keydown.ArrowUp)="scrollUp()"
(keydown.ArrowDown)="move(1)"
(keydown.ArrowUp)="move(-1)"
(keydown.Enter)="selectedPayment()"
(blur)="hideLookUp()"
/>
<span class="approve"> <i class="material-icons status-positive">check</i> </span>
</div>
<div id="lookupRecipientCtn" style="display: block" *ngIf="isLookUp">
<div id="lookupRecipient" #recipientsLookupCtn>
<ul>
<!-- New Recipient -->
<a id="addNewRecipient" (mousedown)="showNewPayment()">
<li class="hlight new-recipient" [ngClass]="{ selected: isNewSelected }">
<div class="items-list-left-icon-ctn">
<p class="items-list-left-icon"><i class="material-icons">person_add</i></p>
</div>
<div class="items-list-info-add" id="addingNewRecipient">
<p class="items-list-name">{{ payToName }}</p>
<p class="items-list-action">Add Recipient</p>
</div>
</li>
</a>
<!-- Old Recipients -->
<!-- TOOD FIX ME -->
<a
(click)="showAgainPayment(template)"
*ngFor="let template of model.templates | templatesFilter: payToName"
>
<!-- <a (click)="showAgainPayment(template)" *ngFor="let template of model.templates"> -->
<li [ngClass]="{ selected: template.selected } && { disabled: !template.id }">
<div class="items-list-left-icon-ctn">
<p *ngIf="template.id" class="items-list-left-icon"><i class="material-icons">person</i></p>
<p *ngIf="!template.id" class="items-list-left-icon">
<i class="material-icons">construction</i>
</p>
</div>
<div class="items-list-info">
<p class="items-list-name">{{ template.name }}</p>
<p class="items-list-contact" *ngIf="template.id && template.defaultContactMethod === 'EMAIL'">
{{ template.p2PPayToEmailAddress }}
</p>
<p class="items-list-contact" *ngIf="template.id && template.defaultContactMethod === 'PHONE'">
{{ template.p2PPayToPhoneNumber | phone }}
</p>
<p *ngIf="!template.id" class="items-list-contact">Creating Recipient</p>
</div>
</li>
</a>
<li><app-loading-linear *ngIf="isLoading"></app-loading-linear></li>
</ul>
</div>
</div>
</form>
Legend
Html element with directive