Lesson Description

The "Dynamic Arrays" Lesson is part of the full, Intermediate Angular: Signals & Dependency Injection course featured in this preview video. Here's what you'd learn in this lesson:

Alex binds form fields to a dynamic array. The array tracks elements by index and responds to updates via form submission, with validation and debounce for input fields. He also highlights the use of a submit button that triggers the form's submit event, as well as the ability to dynamically update specific items in the form data.

Preview

Transcript from the "Dynamic Arrays" Lesson

[00:00:00]
>> Alex Okrushko: --- Now, let's add some of this logic to our template. Right now, we only had our input that's bound. Let's see, we can have a few more things here. This is a description form description. Again, it follows the same kind of pattern. Let me copy again, this is less about typing things, right, that's more about learning. Let's just get this stuff out, and especially I'm going to highlight one more thing here which is super powerful.

[00:00:42]
I probably got a few extra divs here. Form is close, yes, I'm past the form. Yes, okay. Let me paste this in this form, and we're going from our title here. No, I worked the first time. There you go, all right, that's great. So, let's just go over what's being added here. It follows the same pattern, we have this field binding to the form description, right, and then we also have for every form, we'll just have like, if there's an error, show error.

[00:01:31]
And moreover, you can basically create a custom components out of this if you want, and just plug them in. That would work too. The date is here, the location, the input is there. We have some actions and types submit, so we added the button, which is our submit button. And see right now it's not enabled, right, it's disabled because form is invalid.

[00:02:02]
A lot of our required fields are not there yet, right, so it's invalid. And by the way, form button type submit. If you are working with forms, is a really nice thing to have because it's not only on click, it will submit. If at some point you have, like, you can click enter as well, the form will try to be submitted as well. Obviously not the text area, which is just goes to the next way, but the title and others enter propagates up and button type submit picks it up.

[00:02:41]
So button type submit picks it up, and what it will do is it will trigger the submit event on the form itself. So let's add this. In our form, we'll listen for the submit event and we'll do some on submit logic ourselves. So on submit event. So right now we don't have any on submit. Let's add on submit. I'm going to do this event.

[00:03:26]
I think it's forms form submitted event. That should do the trick as well. Let me see if we have some other, just submit event. It's in, we're listening for the submit event, yes, that's right. So this is the default submit event that's part of the HTML, right, so the form is submitted, it would carry the data as well, but we're not really interested in that data.

[00:03:57]
We already have the data as part of our signal. So we'll do a few cool things with this one in a moment. Before we do that, I want to cover another really cool topic, which is our dynamic arrays. If you ever worked with dynamic arrays in template-driven forms, it's very hard. Reactive forms is a little bit easier, but it's still quite challenging.

[00:04:27]
This one is super easy. Again, a lot of thought was put into this. We have a speakers, which is basically our dynamic array. So how can we work with the speaker? The way we work with them is we'll create some methods, methods that will update this data. And this is something that you've been asking, what if I want to update specific things, specific properties, a specific item only, so I'll have the add speaker.

[00:05:06]
We'll have the add speaker and this when I'm adding the speaker, I'm going to just add the new field for it, right? So, I'll create the empty field for this. So let's see, add speaker, so I'll do this event data, and now I need to update the entire object, because it's a signal of this object. So I need to update the entire object, but update has access to the current one.

[00:05:35]
So we'll see the current one, and then what we're going to do is we're going to return the object, the new object. We'll spread all the current other properties, the title, the date, everything else that we have, because we do need to return a new instance, right, that adheres to the same interface. And then on the speaker side, we'll update speakers with all the existing speakers that we had, speakers, and then in this case, just add the empty slot for the new one as well.

[00:06:12]
This is our add speaker, so when we click the button, we'll have a new field for it, which initially will be empty, and then the form field is tied to the speaker and they'll be automatically updating it by index. Super cool. And then if we remove speaker, we'll remove speaker by a specific index, which our form will tell us what's that index.

[00:06:46]
And we'll have this index number, which automatically knows which one's current. Current is current value of this event data, so at whatever point we have, whatever's in the signal value, this is the initial data. Whatever's in the other, this is your index value, the record that you're on, not really. So update is just, think of it this way.

[00:07:23]
So we have some signal, which is signal, signal. Importing signal, no, yes, thank you. So my value, right? So if I have this signal, right, and I'm doing something here and I want to build the new value based on the previous one, right, so I'll have this signal. I can set the new value altogether and this will override whatever I had in the signal before, or I can update this, and I can have my current value for this, which initially will be just my value, and I can say my current value plus new and new value, right?

[00:08:14]
So now after I execute this, my signal will have my value and new value string. Yes, so this is the primitives like strings or numbers. Now, we're working with an object, so whatever object we have there, we need to update that object and the current values of that object are basically passed as a current. See our create event form, all our current data, whatever we entered, title, date, anything else will be there.

[00:08:45]
So, what we do, we need to create a new object, and again, this might be jumping a little bit, so let me just do it a little bit easier. I appreciate the context, thank you. Yes, no worries. So we need to create a function that will return the new object. And the way we create a new object that adheres to the same interface, we can spread all the properties of the previous object.

[00:09:24]
So that means that it's, think of it this way, this is the same as title, current title, and then we have date, current date, and then we have image, current image, and notice it's still complaining, it's like, hey, you're still missing some properties, you're missing description, location, so this is description, and then location, right?

[00:09:58]
That's so cool. So, now we have all the previous values we passed back, right, and then the speakers, we have a new way, the speakers, I need to have my previous speakers' array. I'm spreading, spreading means all the previous values get in there, and then the new ones here. So instead of doing all of this, we'll say, hey, spread all the values, all the properties, all the top level properties into this and create the new object.

[00:10:31]
That's a nice shortcut. Yes, very nice shortcut, and this makes especially important when we talk about immutability, when you do not mutate objects, but you create always a new instance of an object. And this is especially important in, again, state management or in Angular OnPush, whenever you have to provide a new reference for the object, so you have to create a new object with most of the data is the same, update some property.

[00:11:05]
And the reason why it's important, immutability is because we are starting comparing by reference, and it's the easiest comparison because it's super fast, you don't need to go deep into the objects. So immutability is a big friend in all JavaScript frameworks, not only Angular specific. React is based on the immutability as well, and all the other ones are, it's the most basic idea for very fast comparison, super important.

[00:11:44]
So when we have a function that just returns a new object, we can have some sugar syntax, right? If we wrap it with the parentheses immediately, we can drop the return statement altogether, right? So it basically does the same thing, it just returns us a new object. This is again, that's not even Angular, this is TypeScript, JavaScript, pure JavaScript.

[00:12:27]
Cool, so now we updated our event data with the empty slot for a new speaker that we'll get the data for. Removing it's the same idea. The only thing we'll do is event data, we'll update it as well. We'll still read the current and we'll still return the new object, will still spread everything in the current. And by the way, if I do nothing, right, it just creates a new instance of object.

[00:13:01]
If I'm putting anything after this, that's the properties that would be overridden. So if I do this current, it creates a new object with the same values, right? So now I say no, all of that is spread, but the speakers, I want my speaker filter for the specific index. Again, you might do it differently, but the idea is you do need to have a new array instance.

[00:13:36]
Filter filters the items and creates the new array instance. Same idea here, we couldn't just push the speakers into the previous array. So we'll just use the filter. Filter, we don't really care about the item itself, I'm just making sure we didn't import anything useless there. I really care about the index and specific index.

[00:14:09]
I could have spliced, but splice is a way to remove an element or remove and insert another one into an array, but splice is mutative, it's mutating the existing instances. We want to have a new array, so for that reason, we'll use the filter. Filter returns the new instance all the time. So, these are the arguments, the first argument is the value itself, and the second is the index.

[00:14:46]
Since I know which index I wanted to remove, I'll just use that as a comparison, and if I say, hey, if the index of that specific item is not equal to the index that I need to do, then I'll be fine, otherwise, I'll filter. Okay, so this is our remove and add speaker, so right now we have the methods that will change our signal.

[00:15:17]
Now, our signal for speakers, or event data speakers, is not tied to anything yet, right? We tied all the other fields, we have form date, we have form location, but not for the speakers. So, let's do that. And we'll do it by this beautiful block. Again, it's quite a lot to type. I'm going to just, especially telling types, which is great.

[00:15:53]
So I'm going to just paste it, I'm going to walk over this thing. So what did we add here? What we added here is this button to add the speaker, add the speaker button, and what it does, it just creates the new empty slot for the speaker. And then we have, this is the beauty of this dynamic arrays, we're iterating over the speakers in the event data and we're tracking index, so index, you can always use index, it's automatically assigned within the for loop for every element starting from 0.

[00:16:29]
It's zero-based index. If we don't have anything to track by ID or whatever else, right? That's one of the ways to track it by specific index, yes. Yeah, is that oversight or you just for demo purpose because you did not check whether we have a speaker from there, just like you said, the best practice is to use the @if to check first before?

[00:16:56]
Yes, so we need to check for when we're reading from resource. That's a great question. Yes, so we need to check if we have a reading from resource. If we're not reading from resource, that's fine. Moreover, we can have the empty block here as well if we want to. In our case, if it's just nothing, we're just not going to show the input for specific speakers.

[00:17:30]
In fact, see, right now we don't show, we just have the add speaker button, but we don't have any speakers yet in this case. Cool. All right, so now, getting back to this, we're going over our event data with the speakers, right, from the for loop, and then we're going to track the index. And then for each input, we'll field bind this form speakers at specific index, right, so basically in the loop dynamic array would bind for each form speaker to the field.

[00:18:17]
Really cool stuff. And then also we'll add the button like add X, which is remove the speaker, and we'll pass the same index here, right, so that's the index that we have here. I know it's interesting. I hope you see how we work with this, right? So we're iterating over our source, which is our signal over all of those speakers, and we are tracking the index and then, because that's the source, that's a source of truth for the form data, and then for each one, we'll bind the form speaker at that specific index for speakers.

[00:19:14]
Knows that this is an array, and now it knows how to track each field individually. So when we type in, it will update that specific speaker. All right. Let's just see it in action, so for example, description right now, see, disabled. Why is it disabled? Because title is required and we disable if it's not there. Okay, so let's have some title like Angular and Duex workshop.

[00:19:55]
Oh, description. So again, look at this nicely, so if I enter this and I tell her that, hey, this has to be at least 10 characters. If I, and you see there's a debounce. So once I over, there's a one second debounce. See, it's like, so there's a little debounce here as well. Some date, so see, boom, it took a little second to remove the error because it debounces that.

[00:20:48]
Location, we'll have online, right? We can set the date, and again, I'm not even using the Angular components, this is just default browser one. Cool. And then we'll add the speaker, can have multiple, and I say Alex, we'll have some Marco, you know, for example. Let's see what we have as a source here. So we're going to go into the our create event.

[00:21:27]
And, let's see, components. This is our input field components, app root. This is app root, app root, Angular components were our components. This is signal graph. Okay, let me just close it for a second. I think this one. Angular. So I have some compilation issues. Let me see. Yep, that's fine. We still have a lazy chunk. That's awesome.

[00:22:04]
E is not detected. Ah, that's cool. It is detected. All right, now it's detected, that's awesome. Yes, so now it has the form data. I don't have it, okay, but basically what I wanted to show you is, let's just do it quickly again. Get a little workshop. Shop some description. See the location online, for example, I'll just add the speakers.

[00:22:21]
And if I even miss one, for example, I'll just have this Marco. See, our array here knows the array, knows that the zero index is empty, right. And if I add another one. Look, it, in the event data in the speakers, it just created the fourth one. And that's what we did, we have appended a new value, but the value is empty until we add it because that's what it will be tracking.

Learn Straight from the Experts Who Shape the Modern Web

  • 250+
    In-depth Courses
  • Industry Leading Experts
  • 24
    Learning Paths
  • Live Interactive Workshops
Get Unlimited Access Now