@bpost/bp-address-auto-complete-by-component
TypeScript icon, indicating that this package has built-in type declarations

1.1.6 • Public • Published

LibAddressAutocompleteByComponent

This library was generated with Angular CLI version 9.1.9.

Here under, we provide for ome basic information. But this version of the library is also shipped with a tutorial where you can find some code and some videos. Look at the distribution's 'tutorial' directory.

Installation of the library

First install the library:

npm i --save @bpost/bp-address-auto-complete-by-component

Install some dependencies

The library only has one dependency to a translation tool ngx-translate. Intall that dependency by the following:

npm i --save @ngx-translate/core

npm i --save ngx-translate-multi-http-loader

Tutorial

In the distribution, we have added a tutorial to help developers integrate our widget. You will find some source code (an angular application) and some references to videos, listed in the file tutorial/tutorial-videos.txt. Videos are published at youtube.com.

Pre requisites: Have nodeJS and Angular installed

You first need to have nodeJS and Angular installed. installing angular:

npm i -g @angular/cli

Installation of the library

First install the library:

npm i --save @bpost/bp-address-auto-complete-by-component

Install some dependencies

The library only has one dependency to a translation tool ngx-translate. Intall that dependency by the following:

npm i --save @ngx-translate/core

npm i --save ngx-translate-multi-http-loader

Integrate the library in your application ng module

After you have installed the library and its dependencies, you have to declare the libray and the translation module in your application. Typically, you do that in your app.module.ts file. Here is a possible solution:

app.module.ts:

import { BrowserModule } from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { NgModule } from '@angular/core';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { CommonModule } from '@angular/common';
import { HttpClient, HttpClientModule } from '@angular/common/http';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';

import { LibAddressAutocompleteByComponentModule } from '@bpost/bp-address-auto-complete-by-component';
import { MultiTranslateHttpLoader } from 'ngx-translate-multi-http-loader';
import { TranslateModule, TranslateLoader } from '@ngx-translate/core';


export function HttpLoaderFactory(http: HttpClient) {                   // <------
// const i18nResourcePath = environment.i18nResourcePath;
return new MultiTranslateHttpLoader(http, [
    {prefix: './assets/i18n/', suffix: '.json'},
    {prefix: './assets/aacwidget/i18n/', suffix: '.json'}
    // {prefix: /*'./shared/assets/i18n/'*/ i18nResourcePath, suffix: '.json'},
]);
}

@NgModule({
declarations: [
    AppComponent,
],
imports: [
    CommonModule,
    BrowserModule,
    BrowserAnimationsModule,
    HttpClientModule,
    FormsModule,
    ReactiveFormsModule,

    TranslateModule.forRoot({               // <------
    defaultLanguage: 'en',
    loader: {
        provide: TranslateLoader,
        useFactory: HttpLoaderFactory,
        deps: [HttpClient]
    }
    }),

    LibAddressAutocompleteByComponentModule,  // <------
    AppRoutingModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }

Using the MultiTranslateHttpLoader allows you to load the needed resources for the widget, but also the resources needed for your application in case of you are also using the same translation tool.

Copy the resources needed by the widget

After your have included the widget declaration in your ng module, you also need to add the resources also shipped with the distribution. You can find these resources in the following location:

<your_root_dir>/node_modules/@bpost/bp-address-auto-complete-by-component/resources.

Under that directory, you will find an 'assets' dir. Copy the content of that directory to your resources dir. For an angular project, you copy these resources under your 'assets' dir, and as a result, these resources are structured like this:

<your_root_dir>/src/assets/aacwidget

This is the default resource location also used by the MultiTranslateHttpLoader configured in your app.module.ts file (NgModule). You can change these default locations as you want.

Notice the assets/aacwidget resources contains 2 sub-directories:

  • i18n, used by the translation tool, ngx-translate
  • scss, for styling

The styling files have to be added to your project too. The <your_root_dir>/src/assets/aacwidget/scss directory contains 2 files:

  • aacwidget-default.scss
  • aacwidget-custom.scss

The first file, even named as .scss, contains pure css style instructions, while the other is used for some kind of responsive informations and is using scss format.

A common way to do that is by adding the declaration of these file in the <your_root_dir>/src/style.scss (or <your_root_dir>/src/style.css) file of your project. If your project is using pure css, do not include the file 'aacwidget-custom.scss'.

So your style.scss file content can look like this:

style.scss:
/* You can add global styles to this file, and also import other style files */

@import 'assets/aacwidget/scss/aacwidget-default.scss';
@import 'assets/aacwidget/scss/aacwidget-custom.scss';

You can customize the rendering of the widget by just create a new css file where you override the default styles. Don't forget to add it after the default css import.

Integrating the widget in your application

Suppose you have created a new component in your application, called 'widget'. If you have used the angular cli to created it, you should have generated 4 files, maybe like this:

  • widget.component.html
  • widget.component.scss
  • widget.component.spec.ts
  • widget.component.ts

Most of the work to integrate the bpost widget will be done in the 'widget.component.html' and 'widget.component.ts' files. The tutorial is giving 2 examples of integration:

  • a small integration with a few features: widget-simple component
  • a full integration with all features explained: widget-full component.

Here we will give only the simple elements. PLease refer to the tutorial for more details. Videos are also explaining lot of features.

Integrating the widget - html

The html code of your component can look like this:

widget-simple.component.html

<button type="button" (click)="onSelectLanguage('fr')">FR</button>
&nbsp;
<button type="button" (click)="onSelectLanguage('nl')">NL</button>
&nbsp;
<button type="button" (click)="onSelectLanguage('en')">EN</button>
&nbsp;
<button type="button" (click)="onSelectLanguage('de')">DE</button>
&nbsp;
<button type="button" (click)="onSelectLanguage('browser')">Browser</button>

<bp-lib-address-autocomplete-by-component
    [defaultLang]="defaultLanguage"
    [inputLang]="selectedLanguage"
    (addressCompleteEventEmitter)="onAddressComplete($event)"
    (clearInputEventEmitter)="onClearInputEventMessage($event)"
    (validationMessageEventEmitter)="onAddressValidationMessage($event)"
></bp-lib-address-autocomplete-by-component>

In this code, we illustrate the following features:

  • the default language used at application startup
  • the language used by the user if the application is multilingual
  • the capture of the 'address complete' event from the widget
  • the capture of the 'clear input' event from the widget
  • the capture of the 'validation' event from the widget

Integrating the widget - Coding

The code of your compoent can look lke this:

widget-simple.component.ts

import { Component, OnInit } from '@angular/core';
import { TranslateService } from '@ngx-translate/core';

@Component({
selector: 'app-widget-simple',
templateUrl: './widget-simple.component.html',
styleUrls: ['./widget-simple.component.scss']
})
export class WidgetSimpleComponent implements OnInit {

    defaultLanguage = 'en';
    selectedLanguage: string;

    constructor(
        private translate: TranslateService,
    ) { }

    ngOnInit(): void {
    }

    onAddressComplete(event)
    {
        console.log('address complete event message', event);
    }

    onClearInputEventMessage(event)
    {
        console.log('address clear input message', event);
    }

    onAddressValidationMessage(event)
    {
        console.log('address system message', event);
    }

    onSelectLanguage(lang: string)
    {
        if (lang === 'browser') {
            const browserLang = this.translate.getBrowserLang();
            this.translate.use(browserLang);
            this.selectedLanguage = browserLang;
        } else {
            this.translate.use(lang);
            this.selectedLanguage = lang;
        }

    }
}

The most important event handler is the 'onAddressComplete'. Each time an element of the address is modified by the user, an event is emitted. You will have to parse the message and then decide what to do in each case. The content of the message can be interpreted in 3 majors ways:

  • The address is NOT recognized (still not correct nor validated) because at least an element is missing (locality, street, number, box)
  • the address is correct and recognized
  • the address is (seems) correct but is NOT recognized

The 'onClearInputEventMessage' handler is receiving a message when the user is clearing an element of the address, by using the 'cross' indicator available in each element. The message contains the name of the cleared element. For instance: 'STREET_NUMBER'. This is part of an enumeration: 'LOCALITY', 'STREET', 'STREET_NUMBER', 'BOX_NUMBER'.

The 'onAddressValidationMessage' handler is in fact receiving a message when something goes wrong. It thus concerns a message about the 'addressvalidation' process itself, running on the backend. As each element has its own service (see the widget-full component), if one of these services is having some trouble, the system will fail and returns a message telling the system was not able to evaluate the address. The message can look like this:

{
    messageType: "service-unavailable"
    translatedMessage: "service-unavailable"
}

or: (translated in 'fr'):

{
    messageType: "service-unavailable"
    translatedMessage: "Le service n'est pas disponible, veuillez réessayer plus tard."
}

The translatedMessage is given regarding the resources and the currently used language by the widget. (see assets/aacwidget/i18n files)

Message for event onAddressComplete - Address not recognized

In that case, an element of the address is still missing. The content of the event returned by the system is different for each 'missing' element.

If you just selected the locality (or postal code), the message can look like this:

{
    detectedLanguage: "fr"
    isComplete: false
    localityName: "Neufvilles"
    municipalityName: "SOIGNIES"
    postalCode: "7063"
    searchBarString: "7063 Neufvilles"
    string: "7063 Neufvilles"
}

If you selected the street, the message can look like this:

{
    detectedLanguage: "fr"
    isComplete: false
    localityName: "NEUFVILLES"
    municipalityName: "SOIGNIES"
    postalCode: "7063"
    searchBarString: "RUE RAMÉE"
    streetName: "RUE RAMÉE"
    string: "RUE RAMÉE"
}

If you selected the number (street number), the message can look like this (): (): In this case this means your need to provide for a box number.

{
    detectedLanguage: "nl"
    houseNumber: "21"
    isComplete: false
    latitude: 51.154121
    localityName: "WILRIJK"
    longitude: 4.391701
    municipalityName: "ANTWERPEN"
    postalCode: "2610"
    searchBarString: "21"
    streetName: "VOLKERENLAAN"
    string: "21"
}

For each of these 3 messages, you can see the 'isComplete' attribute is on 'false': isComplete: false. This indicates the address is (still) not recognized.

Message for event onAddressComplete - Address correct and recognized

Here the user has entered enough element so that the system could recognized the address. In that case the message can look like this:

{
    boxNumber: "5"
    detectedLanguage: "nl"
    houseNumber: "21"
    isComplete: true
    isCompleteNotificationDone: true
    latitude: 51.154121
    localityName: "WILRIJK"
    longitude: 4.391701
    municipalityName: "ANTWERPEN"
    postalCode: "2610"
    searchBarString: "5"
    streetName: "VOLKERENLAAN"
    string: "5"
}

In this case, the attribute 'isComplete' is on 'true': isComplete: true, and the attribute 'isCompleteNotificationDone' too: isCompleteNotificationDone: true. This indicates the address is recognized.

Message for event onAddressComplete - address (seems) correct but is NOT recognized

Here the user has entered enough elements, but at least has used the option 'not in list' for the street number and/or the box number. In that case the system will tell the address is accepted but conditionally regarding the 'not in list' option has been used. In that case the message returned by the system can look like this:

{
    boxNumber: "24"
    detectedLanguage: "nl"
    houseNumber: "21"
    isComplete: true
    isCompleteNotificationDone: true
    latitude: 51.154121
    localityName: "WILRIJK"
    longitude: 4.391701
    municipalityName: "ANTWERPEN"
    not-in-list: true
    postalCode: "2610"
    searchBarString: "24"
    streetName: "VOLKERENLAAN"
    string: "24"
}

As you can see, the attribute 'isComplete' is on 'true': isComplete: true, and the attribute 'isCompleteNotificationDone' too: isCompleteNotificationDone: true, BUT !!! Another attribute is present in the message: not-in-list: true.

The 'not in list' feature

The 'not in list' feature is used to allow the user to indicate a street number or a box number is not provided in the dropdown list constructed by data coming from the backend. This 'not in list' feature is allowed by default. Of course, you can disable it by just giving an attribute to the widget.

In your html:

<bp-lib-address-autocomplete-by-component
    .....
    [notInListAllowed]="notInListAllowed"
    .....

In your component:

// The 'not in list' feature, if allowed, is only available for the street number and box number address element
// By default, that feature is allowed.
notInListAllowed = false;

With this in place, the 'not in list' feature is disabled.

Pre-filling the widget

Its possible to pre-fill the widget before validating an address. In this version (i.e. 1.0.9) we introduced a new parameter: onFocusShowSuggestionsAfterPrefill, and we have removed the support for 'unstructured' addresses. The prefill structure is now like this:

this.prefilledParameters = new PrefilledParameters(
  {
    municipalityName: 'Wilrijk',
    postalCode: '2610',
    streetName: 'volklorenlaan',
    streetNumber: '',
    boxNumber: '',

    state: true

    onFocusShowSuggestionsAfterPrefill = false;
  }
);
this.minLevel = this.prefilledParameters.minLevel;

In that case, as you can see, you have to define 2 fields in your component like this:

minLevel: number; prefilledParameters: PrefilledParameters;

Where the PrefilledParameters is imported from the library:

import { PrefilledParameters } from '@bpost/bp-address-auto-complete-by-component';

And in the html, you have to provide these fields to the widget:

<bp-lib-address-autocomplete-by-component
    ......
    [minLevel]="minLevel"
    [addressParams]="prefilledParameters"
    .....

The role of the parameter 'onFocusShowSuggestionsAfterPrefill' is to indicate if you want to immediately show the drop down containing the suggestion for a particular address field when one address field got the focus. If that option is on 'false' (the default), when the user set the focus on that field for the first time the suggestions are not shown. The suggestions will only be shown if the user modifies the content of the field, or if the field receives the focus for the second time. So suppose you have prefilled the postal code, the locality, the street and the street number. if the user put the cursor in the street field, nothing will happen. If he puts the cursor in the street number field, nothing will happen. But if the user comes back in the street field, as it is the second times the field receives the focus, the drop down containing the suggestion will be shown, of course only if the system has found some suggestions. This behaviour is valid for each address field independently.

Customizing the component

Your can override some css styles by providing and loading your own css. The aacwidget-default.scss style sheet should not be modified. Just override the styles you want in the custom scss.

You can also customize the content of the labels of the widget. For instance, the english label and placeholder for the 'street' element of the component are: label: 'street name' placeholder: Provide a streetName...

The label and placeholder are given in the ./assets/aacwidget/i18n directory, where you should have put some translation files. Actually we have provided for 4 languages: de, en, fr and nl. Of course, you can add as many language as you want.

Labels can be found at the beginning of each translation files. Here is the default content for en.json:

	"label": {
		"boxNumber": "box number",
		"streetNumber": "house number",
		"municipalityName": "municipality",
		"postalCode": "postal code",
		"streetName": "street name"
	}

And for the placehoder, you can find the corresponding placeholder default at the corresponding address part. For the street name, in the en.json file:

    "street": {
        "placeholder": {
            "input-placeholder": "Provide a streetName..."
        },
        "suggestion": {
            "message": {
                "subl": "<em>{{sub}}</em> is a sub-municipality of <em>{{principal}}</em>"
            }
        }
    },

Its also at that place you can customize the message given in the suggestion list. But take care! The {{sub}} and {{principal}} are variable placeholders used to format the message.

Demo application

To facilitate the integration of this widget, we also have created a demo application shipped with its source code. That demo application is available from npm:

npm i @bpost/bp-address-auto-complete-by-component-demo-application

Just take the bp-address-auto-complete-by-component-demo-application.zip file, uncompress it and launch the application:

ng serve -o

The source code of the demo application can also be found under the 'demo' sub-directory of this distribution

To help windows users to install the demo application, we also provide for a script (batch) file which will install and run the demo application automatically. Just execute: install-and-start-demo.bat, in an empty directory. The installer will create a 'demo' sub-directory, in which you will find the file 'run-demo.bat' you can execute if you want to run the demo again after having closed it.

For your facility, the current distribution contains a file 'install-and-start-demo.bat' which will install and run the demo application automacally.

Online Documentation

Online documentation is also avalable at the following url:

https://www.bpost.be/site/en/address/

Contact us

If you have any question you can send an email to the following address:

EMail: adres@bpost.be

License

License

Copyright (c) 2016 Bpost and other contributors

Licensed under the MIT License

Readme

Keywords

none

Package Sidebar

Install

npm i @bpost/bp-address-auto-complete-by-component

Weekly Downloads

56

Version

1.1.6

License

none

Unpacked Size

2.26 MB

Total Files

77

Last publish

Collaborators

  • bpost_custom_components
  • peeteko
  • u266996
  • kevin_dsouza04
  • bpost_licences
  • wim_rosseel
  • u514567
  • u530539
  • kaising