Custom Angular Schematics — Generating Custom Component (advanced)
Aug 15, 2023
Custom Angular Schematics — Generating Custom Component (advanced)
In this video, we will continue to explore angular schematics and I am going to show you have to create a schematic that will generate a custom component for you with an already pre-injected Angular service. This video is an extension of the previous one where we were implementing the ng-add schematic. I hope you will learn something new today and please enjoy the video. 💥 Angular courses made by Dmytro - https://bit.ly/df-courses 💥 ✂️ Use coupon YOUTUBE_DISCOUNT to get a 10%-off discount ✂️ 🕒 Time Codes: 00:00:00 - Intro; 00:01:04 - Quick walk through the project; 00:04:23 - Implementing the schematics to generate a custom component; 00:07:56 - What is Schematic Schema; 00:11:57 - Define an interface for options; 00:13:00 - Implementing factory function for the schematics; 00:15:44 - About Schematics Templates; 00:21:37 - Continue work on Schematic factory function; 00:34:08 - How to reuse existing schematics; 00:40:06 - Outro; Link to the Project on GitHub:https://github.com/DMezhenskyi/ngx-sc … More about Schematics on Angular Docs:https://angular.io/guide/schematics-f … ↙️ Short Frontend Snacks every week here: Twitter - https://twitter.com/DecodedFrontend Instagram - https://www.instagram.com/decodedfron … LinkedIn - https://www.linkedin.com/in/dmezhenskyi #angular #webdevelopment #schematics #ng
Content
4.48 -> Hey everyone! Welcome, my name is Dmytro
Mezhenskyi and today we continue our talk about
10.4 -> Angular schematics. My internal YouTube statistics
shows that you like my previous video where we
19.2 -> were implementing ng-add schematics so this is
the schematic that is being executed when we
26.32 -> add some certain library to the project to the
angular project via ng at command uh and i saw um
36.88 -> high activity under this video so i decided to
continue and in this video i will show you how
43.44 -> to create another schematic that allows you to
generate some custom component let's say the
51.36 -> component with already injected some service so
this is what we going to implement in this video
60.16 -> so i would suggest you to get started right now
all right first of all let's quickly recap what we
69.12 -> have done in the previous video if you forgot if
you have not seen it please check this out first
76 -> one more time because it most probably you will
not really understand what is going on here
84 -> but for those who have seen it let's quickly
walk through so we created an angular workspace
91.44 -> and we created some empty angular library
using these two awesome commands and
99.12 -> then we created a schematics folder in the root of
the library uh don't be confused not the root of
107.44 -> the workspace root of the library uh there we
created schematics folder and there inside we
114 -> created a collection json file where we described
the list of supported direct oh directive sorry
124.16 -> schematics and there is only one so far it
is ng add this is the schematic that is being
133.04 -> activated when we add our library to the project
using ng add command and what is happening here
143.04 -> once we add this library to the project
uh angular cli looks for the factory
151.52 -> key within this collection json file and then it
tells that our schematic the script that has to
158.8 -> be executed located under the ng add folder right
there and inside the index dl or js file there is
168.4 -> a ng add function uh that will be kind of uh
called in order to create our schematics and
178.56 -> we indeed have this index ds file and there inside
we have our factory function ng-add that will be
186.56 -> called and this whole thing will happen and in the
end we'll update our app model ts file and we will
198.56 -> set up our library we add to the imports
array our library model and everything
206.24 -> will be working fine and we uh deploy our
or better to say we publish our library
215.04 -> to the local npm registry for that i'm using
ferdaccio and you can see that uh i'm running
222.88 -> it locally right here so let's switch to the
terminal and this is basically it so now i
230 -> hope we record everything and there's no there
are no questions of what is going on there i as
238.4 -> i said in the intro in this video we're going to
create another schematics that will be generating
246.48 -> some custom component um this component should
have already injected in the constructor the
257.28 -> uh service that comes from our super ui library
and yeah let's get started and let's get started
266 -> from the collection json file will we are going
to introduce a new schematics right there and
275.2 -> i will name this schematic like super ui component
they should describe also what this schematic is
285.84 -> going to do so we need a description so i'm
gonna say this schematic generates super
294.96 -> component like that awesome the next property we
have to add is obviously factory so factory is
305.36 -> going to be located under the super ui component
folder and there will be index file and we're
314.64 -> gonna trigger the function that i'm going to
name super ui component generator here we go
324.4 -> and now because our new schematic will be getting
some options like we're going to provide the name
334.16 -> for the component right we're going to provide
a path where should be created this component so
340.88 -> we didn't have this for ng at schematic
but here we need it and in order to
350.64 -> achieve this we have to describe the
schema for the schematic describe the
357.2 -> options that we're going to uh get from the
user input when they will type ng generate
364.48 -> uh blah blah super ui component and so on so
that's why we have to introduce a new property
372.16 -> called schema and definitely we have to provide
a path to this file and it's going to be also
380.24 -> under this super ui component folder and i
call it schema and it is json file here we
390.24 -> go and let's maybe add some fancy stuff why
not uh and i would suggest you to provide some
399.28 -> shortcut as example if you use ngcli
you know that instead of writing uh ng
407.68 -> generate component and so on you can just type
ng g component c for component and then some
416.72 -> name whatever you like so we will do the similar
thing for this schematic as well and there is the
426.16 -> property for that it is called aliases and there
inside the array we can define some shortcuts in
436.08 -> my case it will be uh let's use first letters
from here from here from here so it will be
444 -> suk suk or sak doesn't matter uh all right i think
it would be enough so we have everything uh and
455.76 -> now let's create appropriate files and folders so
let's start with the factory i'm going to create a
463.52 -> new folder called super ui component then we will
create a new file it is going to be index index ts
474 -> and also let's close it and also we have to create
a schema right so let's create it also next to
484.56 -> index ts file schema json in this file you should
add content like that all right and here for the
494.8 -> schema key we have to provide this string uh for
id we should provide some id in my case it's going
502.48 -> to be a super ui component and also i need some
title for this schema let's say it is a super
511.92 -> ui library component schema here we go then we say
that it's going to be type of object and as every
523.52 -> object it has properties and here we describe
already properties that we are going to provide
531.92 -> so those are flags that we are providing when
we do um if you know ng generate component then
540.72 -> my uh component and then we provide some
module and then many other options so
547.52 -> those are these properties basically all right
so let's add a few of them i would suggest you
556 -> to have a name in order to provide the name of
the component right so it's going to be name
563.36 -> then we also have to provide a
description that explains what uh
570.08 -> this property is responsible for in our case it
is the name of the component and then we should
579.92 -> define the type of this property and the type
of this property i would say it is a string
590.88 -> cool for now i would say it is enough we can
go forward and introduce a new uh property and
600.08 -> it's going to be the path so means where in our
file system we should create this component right
608.56 -> and i would say that um okay yeah let's add the
description of course so where should be created
619.76 -> the file okay and then we have to define also
the type the type is going to be string as well
632.4 -> then we have to format it and format it to the
path so it will be the proper path for uh to the
642.64 -> folder and um let's add also some fancy stuff and
namely xprompt it's um when you run the schematic
655.52 -> it will stop the execution and it will ask you to
type some value before uh the execution um will
665.04 -> continue you will see it in action no worries
but so far let's say x prompt and we have to
674.48 -> provide the message that should be displayed right
above the input field so we can actually copy
685.04 -> this message and just add question mark um
and the last property is let's say it's uh
696.96 -> default so we can provide some default value
right why not so the default value can be
706 -> source app so let it be there and i think
we are pretty much done so i can save it
718.08 -> so these properties will be passed to our factory
function and i would suggest you before we start
728.64 -> to use these options we have to create some
interface and describe those options so we
736.08 -> have uh strict types intellisense and all these
fancy things that uh typescript give us so i will
747.76 -> create a new file called super component dot ts
and here i'm going to export export interface
761.2 -> super ui components schema like that and we have
two properties their name that is string and we
773.68 -> also have a path that is also string that's
it so now we can uh continue and write our
786.64 -> factory function how did i name this factory
function aha it's going to be super ui component
795.76 -> generator all right so export function super
ui generator and it's going to return another
807.92 -> function all right so if you remember we got here
the tree and schematic context parameters right
818.24 -> but you we don't need for this particular case
those stuff so i leave it blank if you want to
827.52 -> check what is actually taking this function you
can check it right there so but i will close it
835.76 -> uh we're going to return the rule and rule
comes um okay autocomplete doesn't work um
845.84 -> i think uh i think i can fix it no it doesn't
work um i could fix it if i install npm
857.36 -> install angular dev kit schematics and save it
as a dev dependency i think it works because
868.64 -> angular dev kit is dependency for some and
other dependencies so it was installed but
873.84 -> uh we have to explicitly install it in order
to have this uh autocomplete i think someone
881.6 -> left the comment under the first video he was
complaining to uh something similar i believe
889.44 -> his issue was caused by those stuff all right
now we can see the intellisense and i can use it
900.16 -> and add automatically the rule the import uh
and import the rule from devkit schematics
908.72 -> cool uh then options yeah options that we
provide here we can get the access to them
919.44 -> uh as an argument for our factory function so
they will come there and how do they call it super
929.84 -> ui component schema okay let's import it
very very good start and uh let's write the
941.44 -> logic for our uh factory function and
here the interesting things are coming so
949.6 -> um i'm going to introduce a new constant and what
should we add to this constant if you remember in
958.72 -> the previous video we created the file and
there we then we did what we add edit import
966.72 -> to the module things like that but in our case
we we are going to create the whole component
975.2 -> yeah we want to add a lot of stuff and it
would be difficult to write this everything
985.2 -> to write all those stuff so it would be really
cool if we could use some template for that
993.84 -> right and angular schematics allows us to do this
so we can create template files and replace just
1004.08 -> some you know some stuff with variables with the
options that we getting from the user input and
1014 -> let's create such a file i'm going to
create it in this super ui component
1021.52 -> folder so i will name it files and here i have
to create a new file but please pay attention
1032.24 -> on the naming how we have to name
it it starts with two underscores
1040.08 -> then we have to say name and this name should
match the name of the property that we're going
1051.2 -> to provide that we described in our schema right
so uh it would this name will be replaced with
1058.56 -> the actual value that user will provide to
us then you have to use add sign and after
1067.36 -> add sign you define the method that will
be applied to the name and that will
1077.76 -> take the string and dasherize this means that
if you get the name in the comment case it will
1085.04 -> be replaced to the dashed version and how you can
do this you can write dash arrives and two times
1095.6 -> underscore again about these functions like
dasherize we will talk in few minutes i will
1105.84 -> show you how you apply them to the template uh
where they come from but so far like yeah it it
1113.36 -> should be like that then after that we press dot
and then component dot ts and then dot template
1125.12 -> this is the file we have to create inside
this template we should uh provide some code
1135.2 -> right so i will take some regular uh
component from from here so i just copied and
1145.28 -> pasted then i would add a new import and namely
i'm going to import the super ui library service
1158.24 -> and it comes from super ui library all right
so i will remove styles and we have to adjust
1170.88 -> naming and here we will use again this dasherize
and classify uh function helpers namely we're
1182.16 -> going to replace the selector first and here we're
going to use the next construction like that then
1192.24 -> two times uh percent sign and uh then it should be
equal sign and here we should provide some value
1203.36 -> like name but we don't know what kind of format
will be there if it's camel case or something else
1212.64 -> so to be sure that it will be dasherize
we we're going to apply uh this dasherize
1220.48 -> function and i will do it like that pressurize
and is a function so we have to do it like
1228.8 -> that cool then we go to the template and we have
to replace uh this string as well so i will reuse
1239.68 -> this part and replace this hard coded stuff and
maybe let's make it in one line to save some space
1248.56 -> and here we have to also replace this sub ui
leap prefix with something dynamic so we will
1257.52 -> replace it with a name as well but we want to use
camelcase there right and there is the another
1265.2 -> helper function called classify like that cool
and then as i said in the very very beginning
1275.2 -> we have to automatically inject uh the super ui
ellipse service so we will do it right here so
1284.88 -> it's going to be private super ui service
and it is super ui leap service instance
1297.28 -> cool we are done with the template i hope
we forgot nothing so i can save it and then
1306 -> we have to use this template somehow inside
our factory function so i'm going to close it
1314.4 -> and yeah i introduced the constant and i'm
going to name it now well template source and to
1325.36 -> this file to this template we just created
we have to apply our options we have to apply
1334.88 -> our functions that we are using right here
right and in order to do this we have to use
1343.6 -> the helper function called apply and it comes
from also dev kits schematics and this function
1354 -> takes couple of arguments it takes source and
array of rules and the source it is basically our
1365.76 -> template to create this source we also have a
helper function called url that also comes from
1372.96 -> schematics and this url takes uh the string that
leads to our files and the second parameter it
1382.96 -> is an array of rules what kind of rules we'll
see in a second so the first rule we have to
1390.08 -> as i said apply uh all options all functions
to this template and there is a special helper
1399.12 -> function apply templates and this function
takes an object where we provide options and
1408.88 -> functions so we have to provide basically classify
function dasherize function and we have to provide
1416.72 -> the variable name so here i say that for classify
we should provide some function and there is such
1424.8 -> a function already created we just have to
import it from the dev kit core it leaves
1432.64 -> as i said inside the core and there is an
object called strings and inside the strings
1440.48 -> we have classify method you can see
there are a lot of them they can analyze
1447.36 -> uh format to underscore format caramelize
capitalize and use whatever you like but
1455.92 -> for my particular case classify is the proper
option then we have to provide dasherize function
1465.36 -> so for dasherize i will grab it here make sure
that this function should match the object key
1474.64 -> so keep in mind that and also from strings i have
dasherize function as well and what is reminding
1483.92 -> else there is a mining name variable and we will
also provide it right here and it comes from
1493.92 -> our option or better let's say it has options yeah
options and name here we go that's it so this rule
1506.48 -> uh as i said we'll apply all those stuff to our
template and then once we have everything applied
1513.2 -> what we have to do we have to move this into the
proper destination because we have also the path
1521.76 -> property right in order to do this we have also
dedicated function that is called move and it also
1529.84 -> comes from the schematics and as argument it takes
the string where eventually our file should be
1538 -> created right and let's provide such a string so
we will use the option path right and then if you
1548.88 -> remember that angular cli by default they create a
separate folder uh with the component name and put
1560.16 -> all the files inside that folder so we can create
such a folder as well so i will again uh use uh
1569.6 -> use dasherize function from strings and there
i will provide i will provide the options name
1580.64 -> and basically it looks okay but there is a
small issue because if you work on the windows
1588.32 -> this path will be probably not relevant because in
windows you have to use forward slash like that so
1597.12 -> uh we can normalize it we can adjust it and
there is a function for it called normalize and
1606.16 -> this function comes from a dev kit core as well
so i will import it right there make sure that
1615.2 -> it is being imported from the dev kit core and
it is a function so we have to wrap our string
1625.12 -> like that and here we go our template
source is ready now now we have to return
1633.44 -> only something from our factory function
right so uh let me make it smaller
1640.48 -> what we are going to return and we're
going to return such a thing called
1647.2 -> chain like that and this chain takes an array
as an argument and it returns actually it takes
1657.6 -> rules multiple rules that needs to be applied
in this chain and return the one or the kind of
1665.6 -> merged rule so to say and i did it intentionally
i will show you later one we why we would need
1675.12 -> the chain but so far let's use only
uh one rule and it's called mergeus
1685.04 -> and it takes as a argument you can see expect the
source and we have this source actually so this
1692.64 -> is this one i provided and we are pretty much
done yeah we can actually save it and we could
1702 -> try uh to build our schematic and
publish our library and check if this uh
1710.32 -> very basic implementation is working so i just
make sure that i saved everything and we have to
1720.4 -> we have to increment the library version from our
package.json file so i'm gonna say that it's going
1729.28 -> to be version four and now we have to build the
library so i'm going to build the library itself
1738.32 -> first and then if you remember we have to build
separately the schematic itself because we have
1745.92 -> uh typescript files we have to compile
this everything and move appropriate files
1753.28 -> and by the way we have to also adjust our this
post build script that it's good that i opened
1762.24 -> this package file because i forgot to adjust
this we have to actually add uh the following
1769.04 -> lines so we also have to grab all schemas that we
uh created right here and also we have to grab all
1778.64 -> files means all our templates and we should
also copy it to the uh this folder for of our
1787.28 -> library so we have to publish it as well so this
is very important step so i can save this part
1797.6 -> and yeah as i said we build the library first now
we have to build the schematic and i'm going to
1808.24 -> run also npm build command but with this prefix i
say that run the build command for the packet json
1818.24 -> that lives in the library root not in the root of
the workspace itself so uh such a way we're going
1825.92 -> to build the schematic you can see that files
were copied successfully we have to find it
1834.48 -> there as well so there is our super
ui component files everything looks
1840.88 -> pretty well so we are ready to publish it
so i'm going to navigate to this and then
1848.56 -> super ui library and i'm doing to npm publish
here we go my uh new version has been added
1858.24 -> to the local npm registry and now i can go
to the project i just created this is just
1867.6 -> simple angular application i created with ngnu
command and now let's try to type ng at super ui
1876.24 -> library and i defined the registry where i have
to pull this library because i'm losing ferdacho
1883.36 -> locally and i have to provide this parameter to
say that please pull this library from the local
1892.72 -> npm registry cool so i'm running this command
and you can see that ngat schematic has been like
1901.44 -> hooked right so i say that yes i want to execute
ngat schematic and you can see it in action so it
1909.6 -> updates my uh app model ts file you can see and it
was added right there so this is ngat schematic in
1919.84 -> action and now we want to run our new one and
how we do this we type ng generate and then we
1927.84 -> have to provide the name of the library so it's
a super ui leap and after column we have to say
1936.32 -> which exactly schematic has to be involved and
we named our schematic like super ui component
1946.56 -> like that and we have to provide some name yeah
this is the name we described in our schema right
1954.96 -> here uh this is this parameter and i will call
it decoded front end all right cool and now i can
1967.36 -> run this command and now you can see this where
should be created the file so this is exactly
1976.24 -> uh this x prompt property in action uh so it
and also you can see that uh default value has
1985.84 -> been highlighted right here so we can leave it as
it is or you can provide some string like super
1995.68 -> compo nens like that and now i press enter and my
my schematic has been executed you can see that
2005.28 -> my super component has been created and let's have
a look what is inside and um we have the component
2015.84 -> with a proper selector with the super ui service
injected everything looks really super super cool
2026 -> however let's do one more step further what the
problem currently the problem currently is that um
2037.12 -> oh it was created in the wrong all right i had
to type source app and then super component so
2044.24 -> it was created in there in the root of the source
folder but okay it doesn't matter um the problem
2050.96 -> is that we created just a component but component
usually consists from template it consists from
2057.84 -> styles it consists from unit tests so usually
we have four files for one single component
2065.84 -> and should we create them from kind of from from
scratch should we create other files separately
2076.8 -> for every four styles for component view and so on
we could do this but why if we can reuse already
2089.04 -> existing schematic that does exactly what we need
so let's reuse the schematic that default for
2097.36 -> angular and if you want to do that in this chain
of rules we have to introduce the new rule and
2107.28 -> there is a function for that called extern
external schematic and it is a function
2116.16 -> that takes two arguments uh the first one is a
string which exactly schematic should be executed
2125.2 -> should be taken and it is schematics angular then
we have to say that uh which exactly schematic
2138.48 -> name should be uh taken and we say
that in our case it is a component
2145.28 -> right so we should reuse component generator
basically right and the third option
2155.12 -> is options that are provided from the user so
basically this is uh those options so i can
2165.28 -> copy them and provide it that's it the only
reminding thing is here when we merge together
2175.84 -> those two rules we have to define how
it should be merged some merge strategy
2184.16 -> and there is such a merged strategy and
we say that uh we would use override
2192.72 -> strategy you can check there are a few of them
you can read about them more but to be honest i
2200.16 -> don't know all of them i know just few of them
like override this is what i'm going to use
2207.2 -> uh so um it says that if there will be conflict
if we if we are trying to create uh two
2215.92 -> ex two same files and there will be overlap
because there will be we are creating a component
2222.48 -> file and uh schematics angular component will
create uh also the file but we want to override
2230.56 -> this file with uh with our component all right
so that's why we have to use this merge strategy
2239.2 -> and keep in mind it is not merging the content
itself it's um overriding of the file and this
2249.6 -> is pretty much it i will save it and then i will
navigate to the project root and i have to build
2261.92 -> only schematics i believe i know i have to also
increase the package version so it's going to be
2271.68 -> uh version 005 so i'm saving it then i
run i build the library then i'm going to
2282.96 -> build the schematics itself and now i go to the
this super ui and run npm publish one more time
2296.64 -> the fifth version has been uh added deployed
and now let's maybe revert all those stuff we
2306.4 -> can also clean it up and uninstall our library so
we will do everything from you know from the very
2313.84 -> beginning and then i'm going to add this library
using ng add here we go and now i'm going to
2323.04 -> create another super ui component uh again with
the name decoded front end i press enter uh then
2333.52 -> let's type this time proper uh path name so
it's going to be source app super components
2345.12 -> and you can see that we created four files uh also
this angular schematic default schematic updated
2356.56 -> app model for us and it has added our component
right here it created besides the component itself
2365.76 -> it created for us the styles file it created the
html file for the view spec files and also if we
2377.12 -> have a look at the component you can see that
there we have the component that we defined in
2385.36 -> our uh template file you can see that service has
been injected like everything as we wanted to have
2395.28 -> but additionally we got those additional uh
files from the default angular schematic yeah
2405.04 -> it is just so cool all right guys that was it
i hope you enjoyed this video and i hope you
2411.28 -> learned something new today something what
you can already apply in your daily work
2418.16 -> and if it's so please share this video with your
colleagues and friends use your social media
2424.88 -> twitter linkedin and so on don't forget to drop
your comments as well because i would like to know
2431.2 -> your opinion your opinion about schematics about
all my videos maybe have some suggestions drop
2440.16 -> everything right there i read every comment
and try to answer when i have time besides that
2447.76 -> don't forget that i have some video courses
you can check them out following this link
2454.24 -> and it is a great option to support my channel and
in return i promise you some cool knowledge that
2461.92 -> can help you to stand out and warn your colleagues
and this is everything i wanted to mention
2469.52 -> i wish you product week ahead stay
safe and see you in the next video
2481.2 -> you
Source: https://www.youtube.com/watch?v=dADWO1Wh6-4