Developer Insights
Join millions of viewers! Our engineers craft human-written articles solving real-world problems weekly. Enjoy fresh technical content and numerous interviews featuring modern web advancements with industry leaders and open-source authors.
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....
Sep 1, 2023
4 mins
State of Angular Ecosystem - Updates in RxJS, NgRx, Ionic, Nx, Cypress, NgGirls, and more.
In the latest State of Angular Ecosystem, core contributors of major Angular ecosystem projects shared their thoughts on the new APIs released with Angular 14, and how the community is integrating or updating other libraries like NgRx, Nx, Ionic, and RxJS for the release. Panelists also talked about community initiatives and trainings in Angular, including NG Girls and This Is Angular. Here is a complete list of the hosts and panelists that participated in the online event. Hosts: - Tracy Lee, CEO, This Dot Labs, @ladyleet - Nacho Vazquez, Senior Software Engineer, This Dot Labs, @nacho_devc Panelists: - Ben Lesh, RxJs Core Team Lead, @BenLesh - Mike Ryan, Principal Architect, LiveLoveApp & Co-creator, NgRx, @MikeRyanDev - Liam DeBeasi, Lead Developer, Ionic Framework, [@LiamDeBeasi] (https://twitter.com/LiamDeBeasi) - Juri Strumpflohner, Director of Developer Experience at Nrwl, @juristr - Jordan Powell, DX Engineer at Cypress.io, @JordanPowell88 - Shmuela Jacobs, Web Development Consultant, Founder at ngGirls, @ShmuelaJ - Erik Slack, SE Technical Lead at Cisco, Co-Producer of NgXP.show, @erik_slack - Lars Gyrup Brink Nielsen, Co-Founder of This is Learning, @LayZeeDK You can watch the full State of Angular Ecosystem event on This Dot Media's YouTube Channel. Libraries And Tools NgRx with Angular 14 NgRx 14 is in its beta version, and contributors are working on integrations and features, including adopting Angular 14, to highlight both the store package and the NgRx Components Package. The NgRx Store package update will include a number of features and benefits: The team is working to make it easier to implement an NgRx Store, requiring less code. A new createActionGroup() function to simplify and reduce the amount of code it takes to create a group of actions for an NgRx Store. NgRx ESLint Plugin will be added to your project automatically when you install an NgRx store to help improve code implementation best practices. NgRx Component Package NgRx Component is a project that looks toward the future of Angular by improving the process of developing Reactive components using Observable. NgRx Component is completely separate from NgRx store, and it features new improvements, including: - Type checking templates - More control for error handling - Improved performance when you don’t have Zone.js Make sure to check out NgRx 14.0 beta ng add @ngrx/store@next. Nx with Angular 14 Nx version 14 was released three weeks ago, with a minor release (14.2) soon following. With these products, the team focused on reducing configuration for Nx to make it simple to just install Nx in a project, and start working with it immediately. Other updates include: Nx.json file is optional with this release It comes with Angular 14 out of the box It includes ng update for automatic migration to the latest Angular version It includes TypeScript 4.7 support Storybook 6.5 support and upgraded Prettier Preparation for integrating the just released Cypress 10 is on the way Nrwl Nrwl has now officially taken over the stewardship of Lerna.js. Nx was always able to integrate with Lerna directly to publish features, bootstrap, and use Nx for task scheduling. It was only made official recently when the main readme was updated, but Nrwl has already maintained Lerna for a couple of years. The purpose of this is to help the Lerna community continue to evolve. The team already made some updates, released version 5 with security patch support, and deprecated some old packages. Additionally, they removed support for old Node versions, and improved the developer experience. Nrwl has a roadmap for upcoming Lerna features that you can check out. For version 5.1, the team added a very easy opt-in feature for Nx which allows developers to install Nx and start using it without the need for configurations. However, this version allows developers to still have the Lerna commands with Nx as an additional package. Ionic Angular At the most recent Ionic Conf, we learned that Ionic and Angular power about 10% of Apps on the Apple App store, and 20% on the Google Play Store. Ionic 6.1 was released with a number of improvements to UI Components. Ionic is working on a Component Playground feature to be released under the Ionic docs website soon. This feature will help developers interact with the UI, see exactly what it will look like, and switch between iOS mode, Material Design mode, or Dark and Light Design modes. With Capacitor, the Ionic team announced the Native Google Map plugin, a highly requested plugin from the community. Ionic’s next release will come with Angular 14 support. Angular Girls (Ng Girls) Ng Girls is an organization that trains women on the fundamentals of Angular. As physical events return, the team is working on workflows and processes to make it easy to join or host mentoring sessions for Ng Girls. Ng Girls founder Shmuela Jacobs recently released a course that helps developers learn How to Build applications with Angular. You can check out her course to learn more. This Is Angular This Is Learning is the non-profit organization behind the “This is Angular” course. All of the courses on This is Learning are free for anyone, and are also available for anyone to contribute to. Check out the website This Is Learning to learn more! Changes to Angular for Library Authors It is highly recommended that library authors who are not using IVY compilation yet migrate to the latest version before Angular compatibility support is officially removed. This removal could render such libraries unusable with new versions of Angular. The new Standalone APIs give library authors the opportunity to provide independent configuration functions that can be used without the need for Ng Modules. The independent inject function constructors and property initializers allow library authors to try out new patterns that are best suited for libraries and Angular applications. Starter.dev This Dot Labs recently released Starter.dev in beta, which offers starter kits in a variety of languages that allow developers to figure out architecture configurations. Starter.dev has a starter kit for Angular and it is available to test. Check out https://starter.dev to learn more. Other Announcements Our event concluded with the announcement of a new book called The Angular Developer's Nx Handbook by Lars Gyrup Brink Nielsen. Want to learn more about Angular? Check out the official Angular blog and head over to the This Dot blog for more Angular content!...
Jun 27, 2022
5 mins
Advanced NgRx: Building a Reusable Feature Store
Advanced NgRx: Building a Reusable Feature Store As an angular application grows in scale and complexity, so often is the need for state management to help simplify its many moving parts. What often occurs is an increase in the amount of boilerplate involved in managing many feature states, and stores. Increase in store size can often lead to repetitive patterns, much like in poor component design. However, if state is written well, an application can utilize a less common pattern- a reusable feature store- as we attempt to eliminate much of this boilerplate headache. The following proposes a pattern where we’ll create a pattern for properly consolidating several stores, gain consistency across similar features with a reusable store, and address any pitfalls in this pattern. When to use consolidating state management patterns Before we get too deep into consolidating, we should first stop, and assess, when and why we're attempting this task. Why consolidate in the first place? - Reduce repeating patterns in feature design. - Increased maintainability of similar features. - Quicker iterations. - A better shared abstracted layer that can be extended as needed for edge cases. - Similar or extensible UI or data stores. When should you consider consolidating? A hard to answer question, but one that's satisfied by having really good foresight, a roadmap of how an app's features will work, or a set of existing features that may need a few iterations to bring them closer in overall design. What this means for both approaches is that a feature can be initially designed similarly to another, or be made to function similar to another to make it _DRY-er_ (Don't Repeat Yourself) later on. A closer look at the store pattern Now that there's a direction and reason for our efforts, let's look at the pattern using a mock version of photo website - Unsplash - to build out a data store. Let's say we have several states that look like this: ` Fortunately for us, our photo assets follow a very similar pattern. This state is simple as it will contain photos in a simple state. However, we can squash these into one state like this: ` And with that simple bit of code, we've opened up the possibility to reuse a data store per photo type into a single store! For example, a website like Unsplash could use several strategies to fetch and display photos like filtering by photo type on navigation, or pre-fetching chunks of photo types in a resolver. Imagine if each photo type acted as an individual store? That would be a lot of stores to maintain! Building the new state and reducer As this new feature store is built, keep in mind that typings become tricky when you begin to use an indexed interface as a type. Typing pitfalls Typescript doesn't like when we add more properties onto indexed interfaces because it assumes that we'd only be adding properties that follow the initial type we assigned to the index property. In this case Photo[]. For example, this will work: ` But this won't, because PhotoType on selectedPhotoType doesn't overlap in types: ` To overcome this, we can use an Intersection Type like so: ` Defining the reusable part of state We want some amount of flexibility in our store, but we have to tell the new store what features we intend to keep similar in pattern. One way we could do this is by creating a dictionary of features. Building the initial state for the photo types could look like: ` And initial state for the reducer: ` Another win for reusable store pattern Maybe you noticed already, but what if each of the individual states used entities? We could help ourselves, and speed up our dev time some more with the adapter methods and selectors exposed per PhotoType. Our biggest win here comes from the fact that we can still use NgRx Entities even in these seemingly nested states of state. The above piece changes like so: ` And give the state slices an initial state: ` Tying it together with the reducer and selectors Now that we have the state accurately defined. We can access the select slices of our single store using the selectedPhotoType property: ` And for the selectors: ` Again, we can use the entity adapter and leverage entity methods and selectors. Full Code Example Here. Conclusion When working with state management stores in NgRx, it shouldn't be a mess of maintaining boilerplates and changes that affect several data sources with the same store shape. As developers, we want to think of future-proofing strategies that abstract enough, yet still help us understand exactly how the application works. By leveraging a reusable store strategy, we gain consistency with like features, a level of abstraction and sharability between like features, with the ability to extend for edge cases, and easier maintenance....
May 11, 2021
4 mins
Working with NgRx Effects
Working with NgRx Effects Almost every web application will, at some point, need to interact with some external resources. The most classic solution to that would be a service-based approach where components are calling and interacting with the external resources directly through services. In this case, most of the heavy lifting is delegated to the services and a component in this scenario still carries a responsibility to directly initiate those interactions. NgRx Effects provides us with a way to isolate interactions, with the aforementioned services, from the components. Within Effects, we can manage various tasks ie. communication with the API, long-running tasks, and practically every other external interaction. In this scenario, the component doesn't need to know about these interactions at all. Its only requires some input data and then emits simple events (actions). In this article, we will build on top of the application we started in Introduction to NgRx. You can find the entry point for this article on my GitHub repo. If you want to follow this article's code, please clone the repository and checkout the effects_entryPoint tag. ` After cloning, just install all the dependencies. ` and you can see the example app by running ` Getting started In order to add NgRx Effects to our application, all we need to do is use the ng add functionality offered by the Angular CLI. Run the following command: ` It will add and install the @ngrx/effects library to your package.json and scaffold your AppModule to import the NgRx EffectsModule into your application. This is the code that the Angular CLI will generate for you: ` With the setup complete, we can start modifying the app to introduce and handle some API calls using Effects. Design interactions - Actions & Reducers When you're designing new features, I highly encouarge you to first create the actions which we expect to see in the application. Let's look at the example API, which you can clone and checkout: effects_ready branch from this repo. Then, use the npm start command to run it locally. The API consists of the following endpoints: GET /api/photos - returns an array of photos PUT /api/photos/:photoId/like - returns the photo that was liked PUT /api/photos/:photoId/dislike - returns photo that was disliked We can start designing our app interactions by handling how the list of photos is loaded. First, we'll need a trigger action to start fetching the list of photos. Since the request can either return successfully, or with an error, let's model that as well within the actions: ` We have modeled the actions that might occur in the application. Now it's time to handle them properly in the photo.reducer.ts. ` Since we're getting an array of photos, and we're keeping them in the state as an id-indexed map, we just need to transform it into the appropriate shape. Since we assume that the API returns all of the photos, we can replace the whole previous state. Great! We now have a correctly working reducer. However, we don't actually emit any action that will put the data in our Store anywhere in our application. To verify that it works correctly, we can dispatch loadPhotosSuccess action in our AppComponent: ` The data is loaded correctly and all the other functionality is still working as expected. Let's revert this dispatch so we can finally create our Effects, which will allow our available photos to asynchronously load. Create Effects In NgRx, Effects are encapsulated in a regular Angular Injectable class. To let NgRx know to use our class as Effects, we need to add an EffectsModule.forRoot([]) array inside of our AppModule imports: ` ` Inside of the PhotoEffects, we will create properties that will react to specific actions being dispatched, perform some side effect (in this case an API call), and susequently dispatch another action based on the API call result. This flow is presented in the following diagram: In our case, we will listen for the loadPhotos action being dispatched. Then, we will call the PhotoService -> getPhotos() method, which should either return the correct data, or return an error (ie. a network error). Upon receiving data, we can dispatch the loadPhotosSuccess action, and in order to handle possible errors, we might dispatch loadPhotosError: ` The app still doesn't do anything. That's because we need the loadPhotos action to be dispatched somewhere. We can do it on the AppComponent initialization inside of ngOnInit lifecycle hook. ` If we look at our application again, we can see that the correct data has loaded. In the network tab of the Dev Tools, we can see the correct API being called. Liking/disliking still works, at least until we refresh the page. We still don't perform any API calls when we like or dislike a photo. Let's implement that behavior similarly to how we implemented photo loading. The easiest way to accomplish this is by treating the likePhotoand dislikePhoto actions as triggers for the API call, and upon a successful or failed response, emitting a new action. Let's name those updatePhotoSuccess and updatePhotoError: ` Now, in reducer, instead of having separate handling for like and dislike, we can replace it with a single handler for updatePhotoSuccess ` Now, with all actions and reducers in place, all that is left to do is add a new effect responsible for performing API call and emitting a new action for updating the state. ` Conclusion Now, all the functionality is still working, and our data is kept safely on the server. All of this was done without modifying the component's code (except for initial dispatch of loadPhotos). That means we can add some complex logic for how we handle data (ie. add data polling, optimistic update, caching etc.) without requiring the components to know about this. This enables us to keep the codebase cleaner and much easier to maintain. You can find the code for this article's end result on my GitHub repos: * Angular app * Photos API app Checkout effects_ready tag to get the up-to-date and ready-to-run solution. In case you have any questions you can always tweet or DM me @ktrz. I'm always happy to help!...
Mar 11, 2021
5 mins
Strong Typing the State and Actions in NgRx
Strong Typing the State and Actions When working with NgRx store, it is highly recommended to provide strong and explicit types for both the State and Actions. This becomes even more significant as our application will inevitably grow, which means it will need more features and almost certainly some refactoring along the way. This is where strong types might make this process easier and safe. I'll base this article on a simple Angular app where we can display a list of photos that then can be liked or disliked. You can find the source code of this application on my GitHub repo. If you want to follow this article's code, please clone the repository and checkout strongTypingState_entryPoint tag. `` git clone git@github.com:ktrz/introduction-to-ngrx.git git checkout strongTypingState_entryPoint `` After cloning, install all the dependencies: `` yarn install `` You can see the example app by running: `` yarn start -o `` Typing Actions With the latest version of NgRx, typing actions is very straight forward. Quoting the docs: > The createAction function returns a function, that when called returns an object in the shape of the Action interface. The props method is used to define any additional metadata needed for the handling of the action. Action creators provide a consistent, type-safe way to construct an action that is being dispatched. Creating actions for liking and disliking a photo could look like this: ` This creates concise and type-safe actions and action creators all-in-one. It also doesn't produce as much boilerplate as the class approach, which was used in previous versions of NgRx (and can still be found in many production code repositories): ` In this example, we need to create classes for each action that act as action creators. However, it is good practice to extract all possible action types into an enum or a set of consts and a separate type union PhotoActions to use later ie. in reducers. All this behavior is neatly packed into the createAction utility function so for creating new actions, I highly suggest using it. Typing State When it comes to typing state, it's a good practice to type every slice of the state containing a specific feature separately. A good place to include it is a reducer file which will handle this specific slice of the state. For larger projects, you can also keep your state types in a separate file ie. src/app/store/photo.state.ts ` Typing rest of NgRx chain (implicitly) By having both State and Actions strongly typed, all created reducers, selectors, and effects can easily infer further types and keep the rest of our NgRx chain type-safe. ` By providing initialState to createReducer utility function, our photoReducer is strongly typed to operate only on PhotoState type. Each on(...) call uses a TypeScript type inference from the provided action (likePhoto, dislikePhoto) so that ` is actually strongly typed as ` The same rules apply to building selectors from our state ` By providing strong explicit typings for selectPhotoFeature, TypeScript will usually be able to infer types for all the other selectors derived from it. When creating a new derived selector: ` it is equivalent to explicitly typing everything like so ` Not everything use case can be inferred automatically but usually, a small hint for a TS compiler is enough ` state param can't be automatically inferred and has any type by default. Angular will complain about it in a strict mode, so in order to complete the typing, we can explicitly add the proper PhotoState type here. ` Benefits In conclusion, by providing strong typing for just Actions and State, we get typings in other parts of NgRx chain usually for free (or by providing minimal hints for the TS compiler). This means that we can benefit both from our IDE auto completion when writing the code. It also provides us with a safety net in case of doing some refactoring or adding new functionality to the state. For example, if we modify the shape of the state in order to accommodate for a new feature, we will immediately be notified by the TS compiler or our IDE of which other parts of the app chain are affected. This way we can review all of them more easily. When combining that with a high test coverage, we can have a good level of confidence to modify the code without breaking anything in the process. You can find the code for this article's end result on my GitHub repo. Checkout strongTypingState_ready tag to get the up-to-date and ready-to-run solution. If you have any questions, you can always tweet or DM me @ktrz. I'm always happy to help!...
Mar 9, 2021
4 mins
Developer Tools & Debugging in NgRx
Developer Tools & Debugging in NgRx When working on a complex software solution, we often find ourselves scratching our heads over a bug that was reported to us. It's essential to have proper tools to trace the issues which like to hide in our code execution paths. Luckily for the devs using NgRx in their project, the application state is kept in a single location and all the actions that can modify it are easily traceable with some great DevTools. As NgRx adheres to the redux pattern, we can use the same Redux DevTools as we would use for any other Redux base application. This tool is essential for me when debugging an NgRx based application. If you haven't worked with NgRx yet, I recommend reading this post first where I introduced the NgRx pattern into a simple app. Getting started In order to make our NgRx store visible in the Redux DevTools, we need to pull in a module provided by NgRx platform - @ngrx/store-devtools. For the installation instructions, please visit the official installation guide. After installing the Store Devtools using the AngularCLI schematics, the following code is automatically added to our AppModule: ` maxAge property is limited to 25 by default for performance reasons - this is the limit of actions stored in the history tree. logOnly is usually set to true on production build to limit the number of features used when connecting to Redux DevTools. I suggest adding name property to our initial configuration to more easily find our state in the DevTools (as it will show all the other stores which might be used in other tabs open in the browser). ` With that minimal setup, we can already start using the Redux DevTools to start debugging our application. You can access the Redux DevTools in the Redux tab on your browser developers tools. Tracking actions The first thing you can do in the Redux DevTools is track all the actions that have been dispatched within the application. For every selected action, you can see the current state value, what exactly has changed in the state as a result of this action, and the content of action object. Moreover, the extension gives you the possibility to "time travel" your application and skip some of the actions to see how it would affect the end result of the state. You can either manually select the point in time to jump to or replay the whole sequence of action using timeline at the bottom. Those functionalities alone provide us with handful of possibilities on tracking how the state of our app is changing over time and pinpointing the possible issues. Replicating the app behavior Another very powerful feature of the Redux DevTools is tha posibility to dispatch the actions without the need of interacting with the UI. It's available as one of the tabs in the bottom extension's menu: By using this feature, we can dispatch any action we want. This is extremely useful if we find the exact course of actions that is leading to an error, but it's hard or long to replicate using the UI. We can enter and dispatch the desired sequence of actions and get to the troublesome point in the app state with ease and in a reproducible manner. There are a few features that combine well with the aforementioned dispatching technique: - Persisting the state - Commiting and reverting the state When we select the persist option, the extension makes sure that our state is persisted and restored even after we reload the page. The commit option allows us to store the state at the specific point in time and treat it as a starting point (it's like saving the game before going on to fight with the boss 🤓). You can perform as many actions as you want from this point on, but you'll always be able to restore the state to a point in time at which you've done a last commit. The restore functionality is only available in the log monitor and not the inspector. This plays really well with dispatching actions directly from the extension. We can test and debug how our application behaves (ie. via Effects) when dipatching a specific action with always exactly the same comitted state. Also, it's easy to repeat by reverting the state and dispatching the action again. NgRx Store Dev Tools options So far we've covered many use-cases of the Redux DevTools, but we can configure it's behavior to our needs when setting up the StoreDevtoolsModule. In real life applications, our action log might consist of hundreds of actions which might pollute our view of what is happening in the app. We can filter them out directly in the extension but that doesn't solve the issue of the limit on number of actions visible at once. We're still limited by whatever the limit we set, and for performance reasons, we should not take this limit off or set it too high. For debugging purposes, we might only be interested in certain type of actions or definitely know that some actions (ie. the one dispatched by Angular Router) might not be useful to us at the given moment. When setting up our StoreDevtoolsModule we're given 3 ways to filter the actions that will be sent to the Redux DevTools extension: - actionBlocklist - actionSafelist - predicate The first two are the most common ones to use. We can either block specific patters of actions (which we know that are not of interest to us) or we can allow only certain types of actions. Both of them take an array of strings as a value and act as a regex on action type property to filter out only the ones we're interested in. If we want to do more specific filtering, we can use predicate. It takes current state and action as parameters and is called for each dispatched action. To allow action to be passed to the Redux DevTools extension, it must return true. With those techniques, we can narrow the scope of actions visible in the extension and therefore make it easier to get the grasp of what is happening in the app. Conclusion With the tools and techniques mentioned above, you should be able to debug your NgRx based application with a bit more ease. It's important to know the tools you have available so that you can use them when the need arises. In case you have any questions you can always tweet or DM at me @ktrz. I'm always happy to help!...
Mar 1, 2021
7 mins
Introduction to NgRx
Introduction to NgRx Why Angular projects are getting more and more complex these days. With handling all the user interaction, application state and accessing this state in every place, it might be necessary but quickly become over complicated. This is why having a one, global app-wide state management system that can be accessible throughout the application may be very useful in modern frontend application. One of the solutions available for Angular applications is NgRx. What In this post, I will give you a quick introduction on how to get started using NgRx in you Angular application. I'll base this intro on a simple Angular app where we can display a photo which then can be liked or disliked. You can find the entry point for this application on my GitHub repo. If you want to follow this article's code, please clone the repository and checkout entry_point tag. ` After cloning just install all the dependencies ` and you can see the example app by running ` We will convert this application to use the NgRx state management in just few steps. How Key concepts Let's start with introducing a few key concepts and building blocks of NgRx. NgRx is a state management tool inspired by Redux, so the building blocks might be familiar to Redux users. To build and operate on our state, we will need the following basic building blocks: - Store is where state of the application will be stored. It's both an Observable of a state and an Observer of action. - Actions describe all the possible and unique events that can occur within the application. They can occur ie. by user interaction, communication with the server or can be a result of other actions. - Reducers are what binds the actions and the state. All the state changes must occur as result of an action. Those changes are handled by pure functions called reducers. They take the current state and the latest action and compute new state value based on that. - Selectors - to retrieve part of the state that we're interested in, we use pure functions which extract the portion of the state that a given component might be interested in. NgRx flow NgRx makes sure that all the interactions in the application follow a certain unidirectional flow. The following diagram illustrates the general flow of the state: Getting started The easiest way to add NgRx to the project and get started is to use a Angular CLI schematic. ``sh ng add @ngrx/store@latest `` This command will - add the @ngrx/store package to package.json -> dependencies - yarn install or npm install those dependencies - import the StoreModule.forRoot({}, {}) in your AppModule Define Actions The first thing to do after installing the necessary dependencies is to define some actions that can occur in our application. In our case, this can define the following action: - like photo - dislike photo To put that into code, let's create the following file: src/app/store/photo.actions.ts ` In this file, we define all the actions (action creators) that can occur in our app. In general, the shape of the action has to be in the following share: ` The required part is the type property which will be used to identify our action. Other properties are optional and might be used to pass some additional data associated with the event ie. id of the liked/disliked photo. What we've just defined are action creators. They are functions which return an action of a specific type. To create ie. like action we can do it as following: ` Define Reducer Now that we have our actions defined, we need a way to consume them and thus make actual changes to the store's state. As described before, this is done using pure functions called reducers. We could define the functions from scratch using ie. switch case statements, but NgRx comes with some handy helper functions which make this process much nicer. Let's create a file to keep our photo reducer in: src/app/store/photo.reducer.ts ` As you can see, you import the actions which we've defined previously and use them in our reducer. createReducer is an utility function which creates a reducer with a provided initial state. This gives us a nice quick way to define new reducers as well as great type inference. TypeScript knows the shape of state that photoReducer operates on from the shape of initialState object. on(...) function can be considered as case statements within a switch. We define that if we encounter a given action, we produce a new state derived from its previous value and optional properties provided within the action. All this code could be rewritten in the following shape. In my opinion, the construction mentioned above is both more consise and self explanatory as well, so I suggest using it. ` After creating a reducer, we need to let our application know that we want to use it. We can define it in our AppModule file and add it to the properties of the StoreModule.forRoot's first param. ` Define Selectors Now that we've defined both possible actions and reducer to handle them, we need a way to get the data from the store. To do this, we'll create another pure function called selectors. The responsibility of selectors is to transform the whole state object (which can we a really large object in real life examples) into small bits necessary for a specific part of the application. In our case, we need a way to get the photo information along with the number of likes/dislikes that it currently has. Let's create another file in our src/app/store directory src/app/store/photo.selectors.ts ` We are again using the utility function provided with NgRx - createSelector. Because our state can be a nested tree of objects, this enables us to create more complex selectors based on the already existing ones. In this case, we combine selecting a photo slice of our whole state with selection of the whole photo object (in this case most of its props are static). Whenever a number of likes change, we will get a new instance of the photo, which makes detection of changes super easy and performant. Use all the building blocks in our component Now that we've defined all the necessary building blocks, we can finally start using them in our AppComponent. The first thing we need to do is inject the Store service into our component. ` This gives us access to both selecting data from the store (as an Observable) and notifying it about actions happening (by dispatching actions). Now let's select the state of the photo into a component's property and define methods for dispatching like and dislike actions. ` To select data from store, we can basically treat it as an Observable and use pipe operator on it. To select data with our previously created selectors, we can use select operator provided by @ngrx/store package. To dispatch actions and notify the store of it, we can use dispatch() method and feed it with the necessary action (also defined above). Now all that is left to do is hook up all this state and methods into our component's template. ` As you can see, we use async pipe to unwrap the photo$ observable and pass a plain object into the [photo] input. The app-photo component provides two outputs: like and dislike which we can react to with our AppComponent's methods. For clarity purposes, let's define our PhotoComponent in src/app/photo/photo.component.ts (It's already defined within the entry point repo but needs some minor tweaks.) ` and PhotoModule in src/app/photo/photo.module.ts ` Now start your application again and see the result it the browser. You can still like/dislike the photo and the state of the app is stored withing NgRx store. Conclusion As you can see, setting up this example required a bit more code to start with. But when the application grows, this additional code pays off as we get one central place where all the state changes are happening. We can see exactly what actions are being dispatched (ie. by using Redux Devtools) and therefore our application is more maintainable. In case you have any questions you can always tweet or DM at me @ktrz. I'm always happy to help! More articles are coming soon! Do not miss any of them and visit the This Dot Blog to be up-to-date....
Feb 24, 2021
6 mins
NgRx Facade Pattern
The NgRx Facade Pattern was first introduced by Thomas Burleson in 2018 and has gained much discussion in recent years. In this article, we will discuss the pattern, how to implement it in Angular and discuss whether or not we should implement it....
Feb 9, 2021
4 mins
Modular Multi Step Form with NgRx in less than 20 minutes
This is the third part of the ReactiveForm series. Now that you know how to use ReactiveForms and techniques to make it accessible, it's time to do the real thing....
Jan 10, 2020
9 mins
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....
Oct 28, 2019
5 mins
Let's innovate together!
We're ready to be your trusted technical partners in your digital innovation journey.
Whether it's modernization or custom software solutions, our team of experts can guide you through best practices and how to build scalable, performant software that lasts.