Month: June 2017

Intercepting the value change of an @input()

Intercepting the value change of an @input()

I am working on a component that handles pictures upload, for various reasons, the real upload happens externally.
It’s possibile to integrate it in a form or pass to it a callback that is fired after the files are selected.
When I use it within a form, I have another component for showing a progressbar, when I pass to it a callback, I use the embedded progressbar.

The embedded progressbar, needs to know the percentage of the upload, I pass it throught an @input(), when it reaches 100 I want to make the progressbar desappear and get my icon back.

So how to intercept the value?

Well, we have two methods:

1) ngOnChanges

2) set,get

 

input file: how to manipulate an image before uploading

input file: how to manipulate an image before uploading

UPDATE 2017 July 2st
I’ve fixed the source code in order to solve a couple of bug:
1) Files with no exif data crashes the app
2) new Files() on iphone brakes the upload,  formData contains empty files

——

I built an angular2+ component that allows selecting and previewing single images before uploading them through an api.
The component works fine with angular forms.
When the user selects a picture, it often happens that it is not correctly oriented, especially if the picture is taken on the fly from the mobile camera.

The solution is made of three steps:

  1.  Read the exif data and get the orientation
  2.  Accordingly with the orientation, rotate the image by using canvas
  3.  Update the “file” object

In this article I am going to focus on these steps, in a further one, I’d like to  discuss about the whole component (that works with angular form by implementing ControlValueAccessor)

For the steps 1 and 2 I’ve written a little angular provider in order to have a base on which I can add other canvas methods:
(Read the comments in the code below)

After we’ve integrated this provider, we just have to call its methods and update our “file” object
I use  FileReader() in order to show the preview, so I modify the image as soon as I load it.

 

An angular and ionic component for google places autocomplete

An angular and ionic component for google places autocomplete

Many applications need an input for inserting a city or an address.
It is not always a good idea to implement the whole logic in the controller, first of all because we can’t control so well the ngModel and secondly because we could need to use that component in different parts of the application.

I implemented this component on top of some ionic components, but it is very easy to replace the ion-label and ion-input and reuse the same code for a “vanilla” angular project.

What will get in the end of this tutorial, it is a component we can easily integrate in our forms in this way:

types restricts the results that appear in the autocomplete field (see maps api)
returnProperty is the property that we want into the ngModel, in this case just the place_id, by default you”ll get the whole gmaps object

Let’s start with the template:

Nothing special here.
We have the {{label}} passed from the external. #addressInput is needed to find the real <input> tag underneath the ion-input component, of course, the ngModel and a spinner that shows if IsPending is true (while the form is being validate)

Before to see the code of the controller which is the heart of this component, it’s important for you to have an overview of  how forms work in angular and what ControlValueAccessor is.
If you don’t know about it, I strongly advice you to read some good article like this one: https://blog.thoughtram.io/angular/2016/07/27/custom-form-controls-in-angular-2.html

Our component relies on https://angular-maps.com/ (@agm/core) in order to easily interact with google maps, I use it for other stuff in my app, so I’ve decided to use it even here.
In this case it helps to dynamically load the maps api:

Install it before to continue and set up your google api key in your app.module.ts

Finally, the controller (pay attention to the comments):

That’s all.
The thing I’d like to improve is

It is never advisable to directly interact with the dom, we could have problem if we export the app for other platforms not web-based.
I’ll find and post a better solution, probably based on “rederer” .
Do you have any suggestion?

UPDATE

The funcion  validate() is called every time the model changes, so many subscriptions occurres.
The easist, but probably not the best way to avoid it is:


It would be better to find a different way to access to FormControl object, someone pass it to the component through @input()
I’ll give you updates as soon as I find a better way, in the meanwhile any advice is encouraged.