Tiny Gradebook with Angular2: Loading Components Dynamically

Update 9/12/16

For the love of god they changed it again. For the 4th time. Yesh! Anyhow the new new new new way of doing it is outline below in the plunkr. I’ll leave the old way here because it makes me sad to delete all of it. 

 

Plunker Link

 

source code
Small extra step for those of you following along. I added lodash to the project but because lodash does not have a typescript file, you’ll need to make one. It’s easy and you’ll only have to do it once. Just go here and follow the steps for underscore and wherever you seen underscore, type in lodash.

For example

becomes

Vacation!

If you just want to see how to load a component dynamically, skip this and go to the next section

I’m back from vacation and decided that now would be a good time to work on the dashboard. Specifically the widgets.

These widget will have a front and back. The front will display the subject, assignment name, due date, submission status, grade, and will also allow a student to upload their assignment file. Obviously some of the items in the list will be dependent on whether an assignment has been upload. 

On the back will be a short description of the assignment. Clicking the widget will take the student to another page that will give the student all the assignment details. 

Great, now let’s get to it.

Loading Components Dynamically

So each assignment has its own widget and thus it’s own widget component The number of assignments will be coming in from a server(not really, it’s hard-coded into a service), so I’ll have to make a widget component for each assignment. 

First, I need to have a place to put my widgets so I made a div with the id of “widgetContainer”.

The beta has seen various methods come and go, so this is a “new” way that hopefully won’t get changed… again. 

To load a component we will use the viewContainerRef‘s createComponent function. This means we need to get the view container reference of the div with the widgetContainer id. You can do this thru the viewChild annotation. 

What’s the viewChild annotation? As of today, you can find it’s terrible, horrible, not so complete documentation here! Now, let’s get that reference!

First, you must import the required classes. 

Next you’ll use the @ViewChild annotation get a hold of the view reference.

That’s a weird-looking thing isn’t? A quick primer is that every element has at least two things, an ElementRef and a ViewContainerRef. If you use the @ViewChild on something like a div, the default is to return its ElementRef. If you were to use it on some component, it’ll return that components reference. But my div doesn’t have an associated component and I don’t want the ElementRef. So I have to pass in another argument telling Angular 2 what I want. That’s what the second argument is doing. It’s saying, read this element and give me it’s ViewContainerRef. Then, store that reference into a variable which I called “widgetContainer”

 Now that we have a ViewContainerRef I can use its createComponent function. However, that function takes in a componentFactory… Something things are not as easy as we’d like.

To get that factory I’ll need to use the ComponentResolver that we import earlier. First you’ll load it like an other service. 

Then you’ll use its resolveComponent function. –which has almost zero documentation at the time of this writing. 🙂

The function takes in the component and returns a promise. On success of that promise, a factory of that component is returned.

Now that we have our component factory, we can use the createComponent function that I mentioned earlier.

This will create a component and put it NEXT TO the element you selected earlier so that it’ll look like this

Passing Inputs

To be honest I’m not sure if this is a best practice… but it works. The createComponent function returns a component reference object of the component you just created. You can use this object to set any data that you need or call any function that the component has.
For example. Say I wanted to set the name property on my new widget. You’d do it like so.

 

Other Stuff

Here’s is some of the other less interesting things I did.

Header Work

I changed the header so that the “Sign Out” button only shows if a user is logged in. I already have an authentication reducer so I simply made the header component subscribe to that. 

Then in the template, I use the authenticated variable to decide if the block of html should be rendered. 

 

Widget Component

As mentioned wayyy above in the dynamic component creation section, I created the basic widget component. I added a flip animation which is pretty cool in its own right, but there are plenty of tutorials that already exist so I don’t see the need to write about it here.

I also learned how to execute a function when an @Input variable is set. You can read about that here.

Facebooktwittergoogle_plusredditpinterestlinkedinby feather