Become a member
to unlock all features

Level Up!

Access all courses & lessons on egghead today and lock-in your price for life.


    Use Angular Formly Extensions to automatically localize all field labels

    Juri StrumpflohnerJuri Strumpflohner

    In one of the previous lessons we learned about the basic functionality of Formly extensions. In this lesson we're diving a bit deeper and learn how to inject services into Formly Extensions with the example of using ngx-translate to localize all of our form field labels.



    Become a Member to view code

    You must be a Member to view code

    Access all courses and lessons, track your progress, gain confidence and expertise.

    Become a Member
    and unlock code for this lesson




    Lecturer: 0:00 we have looked at formula extensions mainly by adding a data CY property to all of our fields. This extension is quite a simple one. Let's have a quick look. All we do there is to add something to the template options, in this case, a new attribute.

    0:16 Now let's assume we want to do something more complex. For instance, all of our labels on our form fields are right now just hard-coded in English. Now obviously, in a more inaudible application, you want to support multiple languages.

    0:28 One way to translate is, for instance, to use NGX-Translate. I've actually already installed that to have to set up in place. Also, in the AppModule, I have made sure to register here to the Slate Module and as well to have here the assets deployed on my application.

    0:49 Right now I have a DE file, which has the German translation for all of these form field labels. What we could definitely do is we could go now to our app component, and we could say basically to import here the TranslateService, which I have already done. Here, we can see I imported TranslateService. I set the default language to use DE, so German right now.

    1:11 Then if I go to my configuration up here, for instance let's say the first name, I can use the expression properties and say templateOptions.label, this.translate.stream, which will return as an observable and pass in here the first name key.

    1:28 Since in my de.json file I have here the key first name and according to translation in German, this should now work. In fact, what you see here is now we have the key here first name properly translated into German vorname.

    1:43 Again, this is something we don't want to do manually on each of our field configurations. inaudible is perfect example again for an extension. Let's implement that. Again, I create here a new file at the very root here. Let's call it translate.extension.ts.

    1:59 This extension here is a bit more complicated. While the previous extension we just returned a function basically that implemented the prepopulate and postpopulate hooks, in this case, we need to get access to the TranslateService.

    2:10 As we have seen here in our AppComponent, we need to be able to inject that into the constructor of our class and then to use its translate.stream or translate.instantFunction to actually translate the key that we passed in. This example, we need actually the class because then we can basically have the injector inject the TranslateService into the class constructor.

    2:32 Let's call it translateExtension. As mentioned in the constructor here, we would need to get access to the TranslateService. With that, we are set up in terms of having the TranslateService in place.

    2:46 Now we can go and implement the actual prepopulate hook. Again, the prepopulate gets here a field and that's the Formly field configuration. Prepopulate hook here is part of the Formly extensions. Inside here, we can now implement the actual behavior.

    3:04 First of all, what we want to do is we want to again attach here the extension properties just as we have manually done before. We also want to make sure to pass in existing expression property someone might have specified on here. Otherwise, we just create an empty one and then we come to what we actually want to do.

    3:22 We want to set the label, so, templateoptions.label and here we want to basically use our TranslateService. We want to use the stream method. As a key, we just want to use the current label specified on a field configuration. Basically, the one here on our first name for instance specifies a lot of template options.

    3:43 What we can do here is we can just go to field.templateoptions.label. Something we might have to pay attention here is that the template options here might not be specified and so we might run into the runtime error.

    3:55 Also, what we don't want to do is we want to repetitively translate the existing labels so that it doesn't make sense. Therefore, let's here elaborate a bit our example. I am here, exiting here, the template options. If they are not specified, let's just return an empty object.

    4:13 Another thing we definitely want to do here is to create some exit conditions. For instance, one of them is, whenever the template options doesn't have a label defined, we definitely want to return because without its label, we basically here don't have the minimal requirement in order to be able to perform the localization.

    4:32 Furthermore, I don't want to add this expression properties multiple times. Similarly, what I can do to the template options is to add some translated flag and I'm just setting that to true. Then up here, I'm saying whenever that TO.label is defined or I have a right to translate it my Formly expression here.

    4:55 Let's save this. With that we have basically implemented the whole extension. What is left is we need to register that as well. In the previous example we made for the data CI extension, we have just used a simple function and that was enough.

    5:12 In this case, it's a bit different because we need to rely on the dependent injector to provide us the TranslateService. Therefore, we need to register our translate extension in a different manner. Let's go back to the AppModule and scroll down to the very bottom.

    5:27 We need to register it here in a provider's section because we need to rely on our dependency inject mechanism. There is another way Formly allows us to register an extension. What we do is we used that formlyConfig token here.

    5:41 It's multi-true because, obviously, we can register multiple extensions, and we need to use the factory. Let's first of all define the name of our factory function. We are going to implement that very soon, where it is called Register-Translate extension. That has a dependency off to TranslateService.

    6:01 Let's import here the TranslateService again from Translate COR. Now we need to define that Register-Translate extension factory function. We can do that here in our AppComponent, or we can also DAS appended here on our Translate extension, so everything is basically bundled in the same file.

    6:19 Let's create here a new function. Register on Slate extension and we need to get the TranslateService's dependency. Here we transfer to an object, which is the registration of our extension. We get here the extensions. Array DAS is we have in a module.

    6:37 Here it takes an object where the name is Translate extension. Then the extension function itself is by creating a new Translate extension object, basically the object class above here.

    6:53 As the dependency we now pass into TranslateService, with that we have created a new instance of our Translate extension. Let's go back because we need to import out a course here in our file and with that we should be ready to go.

    7:09 Now with that, you can see all the labels are translated automatically by our extensions, even though we don't have any kind of mechanisms specified original Formly configurations...