Skip to content

Angular News : Ngrx, Web Bluetooth, NativeScript, & Angular Translations

Angular’s innovative updates and partnerships continue to move forward and grow each month. The community is constantly moving and introducing interesting topics for Angular and JavaScript developers. In this article we review conversations around the beginnings of the Nativescript and Angular integration, new inventions using APIs like web bluetooth and IoT, solutions the Angular community has created to address translation issues in Angular, and use cases for the popular ngrx.

Featured are experts in Angular including Mike Ryan (@mikeryandev) from the ngrx core team, Olivier Combe (@Ocombe) from the Angular Core Team, Uri Shaked (@Urishaked), a Google Developer Expert and speaker, and TJ Vantoll (@tjvantoll), Principal Developer Advocate at Progress for NativeScript.

Angular + ngrx

The Benefits of Using ngrx with Angular with Core Contributor Mike Ryan

As a core contributor of ngrx, Mike introduces us to the ngrx project. Ngrx is a concise reactive library for Angular. With the need for higher performance, Mike was determined to create a library that had immutable state management for applications. Once this was accomplished, the idea to use observables to express the state changes followed.

Mike explains the value of using ngrx with angular and the benefits of having the ability to manage state and side effects. He also discusses some comparisons between ngrx and redux-observable.

When using ngrx, it is important to consider the state of the application and how many ways this state can change. If there isn’t very much state and the only updates are made with REST APIs, ngrx might not be the best fit. However, when a lot of user interaction is involved and you are making a lot of REST calls or handling webstock and images is a must, using ngrx is highly beneficial.

The path to adopt ngrx is a simple one. Mike explains how developers may go about (slowly) introducing an application they recently built.

{% youtube BxHkI0NUGNQ %}

Angular, NgBeacon, and Bluetooth

Combining Angular, Web Bluetooth, and IoT Hardware with Uri Shaked

Uri Shaked demonstrates what happens when you collide two worlds that you’re passionate about. You create inventions that are fun and exciting. Uri introduces NgBeacon, a bluetooth low energy device capable of running JavaScript code. In this interview, he showcases how the device can broadcast urls through the physical web with the help of a Chrome widget on an iPad.

Electronics is something that Uri explores as a hobby. He mentions that he is a beginner himself, as he had the NgBeacon’s PCB board made in China, and learned how to solder components onto it on his ownr. Uri shares another creation of his, Bonnie, a mascot Shai Reznik uses in all of his instructional videos. Within a few minutes, he is able to connect the 3D printed Bonnie to a phone and command it to say “hi”. Uri then explains how this is possible.

{% youtube SaAy7kHX2Ig %}

Angular Translations + i18n

Building Multilingual Applications Using Angular Translations and i18n with Olivier Combe

Olivier Combe, an Angular core team member, walks us through the difficulties involved with translating apps in Angular. When Angular 2 was released in alpha, Olivier was determined to start a project that would help him learn more about the framework. His first choice was to start a library, so he decided to experiment with angular translate. After discovering that this was something a lot of people needed, he continued to work on it.

When companies are thinking of adding translation to their applications, there are two main things that Olivier addresses as important. The first is whether or not a translation fits into the website design. The second is what solutions are currently available and on the market.

He also explains one of the hardest parts of building a multilingual application is translating strings in your code. Because of this, it is difficult to have one source of data. He also adds that some languages may be harder to translate because of the complexity of characters or structure. One example Olivier gives is creating an app where the language interpretation occurs from right to left, instead of left to right. In this case, one would have to change the wall design in order to adapt to this specific language rule.

Olivier explains the simplest way to overcome these issues is to create a website that is agnostic. i18n can be an option for simplifying angular translation as well. Olivier is currently working on improving the support of this process so that it can be used in code. He’s also looking to improve the way dates and numbers are handled, and perfecting tools. Adding support with i18n so that it can be used in code is also something in the works and stemmed originally from how Google uses closure in its i18n attributes.

{% youtube SK6snNc8eUA %}

Nativescript, Cordova, and Angular

The History Behind the Inner Workings of NativeScript and Angular with TJ Vantoll

TJ shares the history behind how NativeScript was first implemented and why. Before NativeScript, Cordova was the well-known mobile development framework and was great for building simple web apps. However, performance and device capabilities soon became matters in question to both the users and the developers. After realizing the downsides of Cordova, the NativeScript team decided that creating something new from the ground up should be the next step. That was when Nativescript was introduced as a technology that would support building native user interfaces.

TJ talks about the differences between using NativeScript compared to other alternatives that involve Angular in mobile devices. He refers to Cordova and Ionic as examples, and elaborates on how these two frameworks function. TJ covers how JavaScript runs inside a mobile environment with JavaScript Virtual Machine and how it packages native binaries that are then shipped on iOS and Android apps.

The process TJ describes is very similar to how Chrome, using V8, requires an additional mechanism to provide info on window and document objects. TJ also talks about the tight integration between NativeScript and Angular, the perks of this collaboration, and whether or not other frameworks can join in on the partnership as well.

{% youtube CIrh2IF3nrA %}

Stay tuned for more Angular, as new releases become available in this community.

For more information about Angular you can visit http://angular.io.

This Dot Labs is a development consultancy that is trusted by top industry companies, including Stripe, Xero, Wikimedia, Docusign, and Twilio. This Dot takes a hands-on approach by providing tailored development strategies to help you approach your most pressing challenges with clarity and confidence. Whether it's bridging the gap between business and technology or modernizing legacy systems, you’ll find a breadth of experience and knowledge you need. Check out how This Dot Labs can empower your tech journey.

You might also like

You Don't Need NgRx To Write a Good Angular App cover image

You Don't Need NgRx To Write a Good Angular App

NgRx is a great tool that allows you to manage state and side effects in Angular applications in a Redux-like manner. It streamlines state changes with its unidirectional data flow, and offers a structured approach to handling data and side effects. Numerous posts on our blog detail its strengths and affiliated techniques. Some Angular developers even argue that incorporating NgRx is imperative once an app expands beyond two features. While NgRx can undoubtedly enhance an Angular application or library by simplifying debugging, translating business logic into code, and improving the architecture, it does present a steep learning curve. Despite the provocative title, there is some truth to the statement: your app or library may indeed not need NgRx. Surprisingly, I successfully developed a suite of enterprise Angular libraries over five years without involving NgRx. In that project, we decided to opt out of using a state management library like NgRx because of its steep learning curve. Developers with varying levels of Angular expertise were involved, and the goal was to simplify their experience. My bold assertion is that, with careful consideration of architectural patterns, it is entirely possible to develop a robust app or library using only Angular, without any third-party libraries. Employing select design patterns and leveraging Angular's built-in tools can yield a highly maintainable app, even without a dedicated state management library. Having shared my somewhat audacious opinion, let me now support it by outlining a few patterns that facilitate the development of a maintainable, stateful Angular application or library without NgRx. Services and the Singleton Pattern Services provided in root` or a module yield a shared instance across the entire app or module, effectively rendering them singletons. This characteristic makes them ideal for managing and sharing state across components without requiring a dedicated state management tool like NgRx. Particularly, for small to medium-sized applications, a "state service" can be a straightforward and effective alternative to a comprehensive state management solution when implemented correctly. To accurately implement state in a singleton service, consider the following: - Restrict state data to private properties and expose them only through public methods or observables to prevent external mutations. Such a pattern safeguards the integrity of your state by averting unauthorized modifications. - Utilize BehaviorSubjects or signals to enable components to respond to state changes. Both BehaviorSubject` and `SettableSignal` retain the current value and emit it to new subscribers immediately. Components can then subscribe to these to receive the current value and any subsequent updates. - Expose public methods in your service that manage state modifications to centralize the logic for updating the state and incorporate validation, logging, or other necessary side effects. - When modifying state, always return a new instance of the data rather than altering the original data. This ensures that references are broken and components that rely on change detection can accurately detect changes. Good Component Architecture Distinguish your UI components into stateful (containers) and stateless (presentational) components. Stateful components manage data and logic, while stateless components merely receive data via inputs and emit events without maintaining an internal state. Do not get dragged into the rabbit hole of anti-patterns such as input drilling or event bubbling while trying to make as many components presentational as possible. Instead, use a Data Service Layer to provide a clean abstraction over backend API calls and handle error management, data transformation, caching, and even state management where it makes sense. Although injecting a service into a component technically categorizes it as a "smart" component, segregating the data access logic into a separate service layer ultimately enhances modularity, maintainability, scalability, and testability. Immutability A best practice is to always treat your state as immutable. Instead of modifying an object or an array directly, you should create a new copy with the changes. Adhering to immutability ensures predictability and can help in tracking changes. Applying the ChangeDetectionStrategy.OnPush strategy to components whenever possible is also a good idea as it not only optimizes performance since Angular only evaluates the component for changes when its inputs change or when a bound event is triggered, but it also enforces immutability. Change detection is only activated when a different object instance is passed to the input. Leveraging Angular Router Angular's router is a powerful tool for managing application state. It enables navigation between different parts of an application, allowing parameters to be passed along, effectively using the URL as a single source of truth for your application state, which makes the application more predictable, bookmarkable, and capable of maintaining state across reloads. Moreover, components can subscribe to URL changes and react accordingly. You can also employ router resolvers to fetch data before navigating to a route, ensuring that the necessary state is loaded before the route is activated. However, think carefully about what state you store in the URL; it should ideally only contain the state essential for navigating to a specific view of your application. More ephemeral states, like UI state, should be managed in components or services. Conclusion Angular provides lots of built-in tools and features you can effectively leverage to develop robust, maintainable applications without third-party state management libraries like NgRx. While NgRx is undoubtedly a valuable tool for managing state and side effects in large, complex applications, it may not be necessary for all projects. By employing thoughtful design patterns, such as the Singleton Pattern, adhering to principles of immutability, and leveraging Angular's built-in tools like the Router and Services, you can build a highly maintainable and stateful Angular application or library....

A Guide to (Typed) Reactive Forms in Angular - Part II (Building Dynamic Superforms) cover image

A Guide to (Typed) Reactive Forms in Angular - Part II (Building Dynamic Superforms)

In the first blog post of the series, we learned about Angular reactive forms and the data structures behind them. When developing real-world applications, however, you often need to leverage dynamic forms, as writing boilerplate for every form and its specific cases can be tedious and time-consuming. In certain situations, it may even be necessary to retrieve information from an API to construct the forms. In this post, we will go over a convenient abstraction we can create to build dynamic and adaptable forms without repeating boilerplate. The trick is to create a "view model" for our data and use a service to transform that data into a reactive form. I was first introduced to this approach by my friend and former teammate Thomas Duft, and I've been using it ever since. The approach outlined in the linked article worked great with untyped forms, but since now we can get our forms strictly typed, we'll want to upgrade it. And here is where it gets a bit tricky. Remember how I mentioned you shouldn't predeclare your form groups earlier? If you want to recursively create a form from a config, you just have to. And it's a dynamic form, so you cannot easily type it. To solve the issue, I devised a trick inspired by a "Super Form" suggested by Bobby Galli. Assuming we will have interfaces defined for our data, using this approach, we can create dynamic type-safe forms. First, we'll create types for our form config: `TypeScript // this will be our ViewModel for configuring a FormGroup export class FormSection | FormField | (FormSection | FormField)[]; } = any > { public title?: string; public fields: T; constructor(section: { title?: string; fields: T; }) { this.title = section.title; this.fields = section.fields; } } // Let's define some editor types we'll be using in the templates later export type FormEditor = | 'textInput' | 'passwordInput' | 'textarea' | 'checkbox' | 'select'; // And this will be a ViewModel for our FormControls export class FormField { public value: T; public editor: FormEditor; public validators: Validators; public label: string; public required: boolean; public options?: T[]; constructor(field: { value: T; editor: FormEditor; validators: Validators; label: string; required: boolean; options?: T[]; }) { this.value = field.value; this.editor = field.editor; this.validators = field.validators; this.label = field.label; this.required = field.required; this.options = field.options; } } ` And then we'll create some type mappings: `TypeScript // We will use this type mapping to properly declare our form group export type ControlsOf> = { [K in keyof T]: T[K] extends Array ? FormArray> : T[K] extends Record ? FormGroup> : FormControl; }; // We will use this type mapping to type our form config export type ConfigOf = { [K in keyof T]: T[K] extends (infer U)[] ? U extends Record ? FormSection>[] : FormField[] : T[K] extends Record ? FormSection> : FormField; }; ` And now we can use our types in a service that will take care of creating nested dynamic forms: `TypeScript import { Injectable } from '@angular/core'; import { AbstractControl, FormArray, FormControl, FormGroup, } from '@angular/forms'; import { ConfigOf, ControlsOf, FormField, FormSection } from './forms.model'; @Injectable({ providedIn: 'root', }) export class FormsService { public createFormGroup>( section: FormSection> ): FormGroup> { // we need to create an empty FormGroup first, so we can add FormControls recursively const group = new FormGroup({}); Object.keys(section.fields).forEach((key: any) => { const field = section.fields[key]; if (Array.isArray(field)) { group.addControl(key, this.createFormArray(field)); } else { if (field instanceof FormSection) { group.addControl(key, this.createFormGroup(field)); } else { group.addControl(key, new FormControl(field.value, field.validators)); } } }); // and we need to cast the group to the correct type before returning return group as unknown as FormGroup>; } public createFormArray>( fields: unknown[] ): FormArray> { const array: FormArray> = new FormArray( [] ) as unknown as FormArray>; fields.forEach((field) => { if (field instanceof FormSection) { array.push(this.createFormGroup(field)); } else { const { value, validators } = field as FormField; array.push(new FormControl(value, validators)); } }); return array as unknown as FormArray>; } } ` And that's it. Now we can use our FormService` to create forms. Let's say we have the following User model: `TypeScript export type User = { email: string; name: string; } ` We can create a form for this user from config in the following way: `TypeScript const userFormConfig = new FormSection>({ title: 'User Form', fields: { email: new FormField({ value: '', validators: [Validators.required, Validators.email], label: 'Email', editor: 'textInput', required: true, }), name: new FormField({ value: '', validators: [Validators.required], label: 'Name', editor: 'textInput', required: true, }) } }); const userForm = this.formsService.createFormGroup(userFormConfig); ` If we would check the type of userForm.value` now, we would see that it's correctly inferred as: `TypeScript Partial ` Outputting the Dynamic Forms To display the dynamic forms, we can write a simple component that takes the FormSection` or `FormField` as an `Input()` along with our `FormGroup` and displays the form recursively. We can use a setter to assign either field` or `section` property when the view model is passed into the component, so we can conveniently use them in our template. Our form component's TypeScript code will look something like this: `TypeScript import { Component, Input } from '@angular/core'; import { FormField, FormSection } from '../forms.model'; import { FormArray, FormGroup } from '@angular/forms'; @Component({ selector: 'app-form', templateUrl: './form.component.html', styleUrls: ['./form.component.scss'], }) export class FormComponent { private fieldConfig?: FormField; private sectionConfig?: FormSection; private arrayConfig?: (FormSection | FormField)[]; private sectionFieldsArray?: [string, FormField][]; @Input() public set config( config: | FormField | FormSection | (FormSection | FormField)[] ) { this.fieldConfig = config instanceof FormField ? config : undefined; this.arrayConfig = Array.isArray(config) ? config : undefined; this.sectionConfig = config instanceof FormSection ? config : undefined; this.sectionFieldsArray = Object.entries(this.sectionConfig?.fields || {}); } public get sectionFields(): [string, FormField][] { return this.sectionFieldsArray || []; } public get field(): FormField | undefined { return this.fieldConfig; } public get section(): FormSection | undefined { return this.sectionConfig; } public get array(): (FormSection | FormField)[] | undefined { return this.arrayConfig; } ngAfterViewInit() { console.log(this.arrayConfig); } @Input() public key!: string; @Input() public group!: FormGroup; public get sectionGroup(): FormGroup { return this.group.get(this.key) as FormGroup; } public get formArray(): FormArray { return this.group.get(this.key) as FormArray; } } ` And our template will reference a new form component for each section field in case we have passed in a FormSection` and it will have a switch case to display the correct control in case a `FormField` has been passed in: `HTML {{ field.label }} {{ section.title }} ` That way, we can display the whole form just by referencing one component, such as `HTML ` Check out an example on StackBlitz. In the next (and last) post of the series, we will learn about building custom Form Controls....

Being a CTO at Any Level: A Discussion with Kathy Keating, Co-Founder of CTO Levels cover image

Being a CTO at Any Level: A Discussion with Kathy Keating, Co-Founder of CTO Levels

In this episode of the engineering leadership series, Kathy Keating, co-founder of CTO Levels and CTO Advisor, shares her insights on the role of a CTO and the challenges they face. She begins by discussing her own journey as a technologist and her experience in technology leadership roles, including founding companies and having a recent exit. According to Kathy, the primary responsibility of a CTO is to deliver the technology that aligns with the company's business needs. However, she highlights a concerning statistic that 50% of CTOs have a tenure of less than two years, often due to a lack of understanding and mismatched expectations. She emphasizes the importance of building trust quickly in order to succeed in this role. One of the main challenges CTOs face is transitioning from being a technologist to a leader. Kathy stresses the significance of developing effective communication habits to bridge this gap. She suggests that CTOs create a playbook of best practices to enhance their communication skills and join communities of other CTOs to learn from their experiences. Matching the right CTO to the stage of a company is another crucial aspect discussed in the episode. Kathy explains that different stages of a company require different types of CTOs, and it is essential to find the right fit. To navigate these challenges, Kathy advises CTOs to build a support system of advisors and coaches who can provide guidance and help them overcome obstacles. Additionally, she encourages CTOs to be aware of their own preferences and strengths, as self-awareness can greatly contribute to their success. In conclusion, this podcast episode sheds light on the technical aspects of being a CTO and the challenges they face. Kathy Keating's insights provide valuable guidance for CTOs to build trust, develop effective communication habits, match their skills to the company's stage, and create a support system for their professional growth. By understanding these key technical aspects, CTOs can enhance their leadership skills and contribute to the success of their organizations....