being is meaning

I am asking to become aware that there is another option. Put it all off. Just yourself — what does being feel like? To me it feels like meaning. The real meaning of life. There is much more to this…

Smartphone

独家优惠奖金 100% 高达 1 BTC + 180 免费旋转




Managing File Uploads With NgRx

In this article we will build a fully-functional file upload control, that is powered by Angular and is backed by an NgRx feature store. The control will provide the user with the following features:

As an added bonus, we will briefly dive into building the server-side ASP.NET Core WebAPI Controller that will handle the file uploads.

If you are new to Angular, then I recommend that you check out one of the following resources:

For context, this article assumes you are using the following npm package.json versions:

Before diving into building the file upload control, make sure that you have the following in place:

$ ng g service file-upload

Because we are using the HttpClient to make requests to the backend, we need to inject it into our service. Update the constructor line of code so that it looks as follows:

constructor(private httpClient: HttpClient) {}

One way to accomplish this would be to do the following:

Let’s create a new public method named uploadFile to the service. The method will take in a parameter file: File and return an Observable<HttpEvent<{}>>.

The completed file-upload.service.ts will look as follows:

To keep your NgRx store organized, I recommend creating a separate Upload File Feature Store. Let’s bundle it all together in a module named upload-file-store.module.ts and keep it under a sub-directory named upload-file-store.

Create a feature store module using the following command:

$ ng g module upload-file-store --flat false

Create a new file underneath the upload-file-store folder, named state.ts. The contents of the file will be as follows:

Create a new file underneath the upload-file-store folder, named actions.ts. This file will hold the actions we want to make available on this store.

We will create the following actions on our feature store:

The final actions.ts file will look as follows:

Create a new file underneath the upload-file-store folder, named reducer.ts. This file will hold the reducer we create to manage state transitions to the store.

We will handle state transitions as follows for the aforementioned actions:

Create a new file underneath the upload-file-store folder, named effects.ts. This file will hold the effects that we create to handle any side-effect calls to the backend API service. This effect is where most of the magic happens in the application.

Let’s add the necessary dependencies to our constructor as follows:

Let’s create a new effect in the file named uploadRequestEffect$.

A couple comments about what this effect is going to do:

The effect will look something like this:

This method will be responsible for mapping a specific HttpEventType to a specific Action that is dispatched.

This method will be responsible for handling any errors that may be thrown from the HttpClient during requests. I am making use of a neat library from npm named serialize-error to give me a predictable error.message no matter what type of error is thrown.

Install the library as so:

$ npm install serialize-error

The completed effect will look something like this:

Create a new file underneath the upload-file-store folder, named selectors.ts. This file will hold the selectors we will use to pull specific pieces of state out of the store. These are technically not required, but strongly encouraged. Selectors improve application performance with the use of the MemoizedSelector wrapper. Selectors also simplify UI logic.

We will create a selector for each significant property of the state. This includes the following properties:

The completed selectors file will look something like the following:

We now need to update the feature module UploadFileStoreModule to wire-up the store.

The completed UploadFileStoreModule should look similar to this:

Make sure to import this new UploadFileStoreModule where it is needed. In this example, we will import this into the AppModule as we do not have any lazy-loaded features.

Last, make sure that you update your AppModule to import the StoreModule.forRoot and EffectsModule.forRoot.

An updated AppModule may look as follows:

Now that we have the foundation laid out for us we can turn our attention to the user interface and wire-up a new component to the UploadFileStore that we created to manage our process.

This will be the fun part!

Let’s start by creating a brand-new Component. This component will consist of the following elements:

$ ng g component upload-file

We need to wire-up our store into this component for use. Let’s start by injecting the store into the constructor. The finished constructor should look something like this:

Let’s create six (6) public fields on the component. A good practice is to place $ as a suffix so that you know these are Observable and must be subscribed to in the template.

Let’s hook these up to the store in our ngOnInit life-cycle hook.

Let’s add uploadFile, resetUpload, and cancelUpload methods to connect our button clicks to dispatch actions in the store.

The finished component *.ts file should look similar to the following:

We are going to add five (5) major parts to our upload file component.

There is no upload file button, rather we will make use of the built-in input component and hook to the change event. Any time a file is added to the form this event will fire. We also only want to display this form if we are accepting new files to be uploaded, i.e. it has failed or it is ready. We will use the *ngIf structural directive to help here referencing our isReady$ and hasFailed$ observables.

This message will be displayed when the progress is greater than or equal to 0% and the UploadStatus is Failed. We will use *ngIf to only display if it's in this state using the isInProgress$ selector value. We will set the text of the progress message to the progress$ selector value.

This button will utilize the *ngIf to only display if the upload is in progress using the isInProgress$ selector value. The click event will trigger the dispatch of the UploadCancelAction.

This button will utilize the *ngIf to only display if the upload is complete using the completed$ selector value. The click event will trigger the dispatch of the UploadResetAction.

This button will utilize the *ngIf to only display if hasFailed$ selector value returns true. The actual error message is pulled from the error$ selector value.

For formatting let’s add a few simple classes to our component stylesheet:

For the purposes of this article we will add our new UploadFileComponent component to our AppComponent. The template will look as follows:

<app-upload-file></app-upload-file>

For those of you brave souls that have made it this far… You might be asking what the backend API endpoint looks like. Well, here's an example ASP.NET Core Controller offered free of charge ;-)

I always like to provide working code examples that follow the article. You can find this articles companion application at the following repository:

It’s important to remember that I have implemented these best practices in several “real world” applications. While I have found these best practices helpful, and maintainable, I do not believe they are an end-all-be-all solution to your NgRx projects; it’s just what has worked for me. I am curious as to what you all think? Please feel free to offer any suggestions, tips, or best practices you’ve learned when building enterprise Angular applications with NgRx and I will update the article to reflect as such. Happy Coding!

Add a comment

Related posts:

My jeans may be ripped

But my Character isn’t!. “My jeans may be ripped” is published by perfectly IMPERFECT.

Reasons to Block Someone on the Internet

I love the option to block people on any platform. It's a necessity these days. Because some folks just don't get how the internet works. Or what it even is! Now, in case you feel bad about blocking…

Find something to do in life that seem work to others and fun to you.

I remember the feeling when I ran my first computer program, I felt deep sense of satisfaction. And after that day everytime I code some program it gives me same feeling. I used to write computer…