In today’s post, I want to showcase several Angular framework features in one example. More specifically, we’ll use standalone components, signals with model() and input(), as well as forms.
Our goal is to build a reusable date-range picker component to select two dates:
To do so, let’s create a standalone component with two HTML date inputs (no need for component libraries!):
We use ngModel
(which is from FormsModule
) to capture the current value selected by the user and set a default value for those dates if needed. To do so, let’s use two signals created by the model()
function from @angular/core
:
Two important things to note:
- These two variables are signals and work seamlessly with
ngModel
- These variables enable two-way data bindings with the parent component as follows:
start
and end
are signals as well. We can use those signals to pass a default value to the child component or keep that value empty if we don’t want any:
And that code is 100% functional as-is. No need for template-driven forms or reactive forms! Now, let’s add some features to our date-range picker component. Let’s say we want to enforce the rule that the start date cannot be after the end date and vice versa. The following bindings do the trick using the min
and max
HTML attributes:
Because this is all based on signals, it’s all reactive by default. Changing the start date or the end date automatically updates the range of what’s selectable in the other date input:
Adding more features is now as easy as adding more signals and bindings. For instance, I want to enforce a minimum start date. I added a new signal input called minDate
and I bind it to the min
attribute of our startDate
:
And then, in the parent component, we can pass a minimum start date:
You can find that code example in action on Stackblitz here. Note that our date range picker has less than 20 lines of code and relies on basic HTML features (input
, min
, max
) instead of adding dependencies that would impact performance.
Please email me if you’d like me to add more features to that example in a future post. I’m always happy to cover what really matters to most people reading these posts.