File

src/app/sending-money/auto-complete/auto-complete.component.ts

Implements

OnInit OnChanges

Metadata

selector app-auto-complete
styleUrls auto-complete.component.css
templateUrl ./auto-complete.component.html

Index

Properties
Methods
Inputs
Outputs

Constructor

constructor(templateService: TemplateService, app: AppState, route: ActivatedRoute)
Parameters :
Name Type Optional
templateService TemplateService no
app AppState no
route ActivatedRoute no

Inputs

defaultTemplateId

Type: string

Outputs

create $event type: EventEmitter
pay $event type: EventEmitter
payAgain $event type: EventEmitter
update

Methods

hideLookUp
hideLookUp()
Returns : void
isToWhoNotValid
isToWhoNotValid()
Returns : any
move
move(delta: number)
Parameters :
Name Type Optional
delta number no
Returns : void
ngOnChanges
ngOnChanges(changes: SimpleChanges)
Parameters :
Name Type Optional
changes SimpleChanges no
Returns : void
ngOnInit
ngOnInit()
Returns : void
payToNameChanged
payToNameChanged(value: string)
Parameters :
Name Type Optional
value string no
Returns : void
resetAutoCompleteForm
resetAutoCompleteForm()
Returns : void
scrollDown
scrollDown()
Returns : void
scrollUp
scrollUp()
Returns : void
selectedPayment
selectedPayment()
Returns : void
showAgainPayment
showAgainPayment(template: Template)
Parameters :
Name Type Optional
template Template no
Returns : void
showLookUp
showLookUp()
Returns : void
showNewPayment
showNewPayment()
Returns : void

Properties

autocompleteform
autocompleteform:
Decorators : ViewChild
filterValue
filterValue: string
Type : string
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
Component
Html element with directive

results matching ""

    No results matching ""