So time for some inheritance and for a base class.
I want to add a base class which basically has template element host element an element in it which
does this job of selecting elements in the DOM which has the attach method which we always need ends
on so which basically manages all these shared functionalities which our classes that actually render
is something to the DOM have in common.
So for that above my project input and also the project list class.
So basically here I'll add the component base class.
Now the name is up to you but I'll name it component because you might notice term from react or angular
if you work with that.
And even if you didn't work with that you can think of these classes as you will I user interface components
which we rendered to the screen and every component is in the end a render arable object which has some
functionalities that allow us to render it and then the concrete instances or the inherited classes
add extra functionality which this specific component needs.
So what goes into the general component class then.
Well I would say these three elements for sure template element host element and element.
Now we do have a problem here however regarding the types the template element will always be h HTML
template element.
But the host element doesn't always have to be a div.
For example when we will add a project item class we'll render dead in a project list and not directly
in our root div here.
So that's not always a death.
And this year well it's always an H to Al element.
We can certainly settle on that but like in the case of the project input class we actually know that
it's some more specific form of it.
It's the HDL form element.
So we would lose this extra information if we restrict ourselves to always having just an H2 html element
there without storing more specific information.
So how can we work around that.
Well by not just using inheritance but by creating a generic class here where when we inherit from it
we can set the concrete types for Dad we add angle brackets after the class name and then Q identifiers
of our choice like t and you which would be common choices and now we also can add some constraints
here and say that t will certainly be some kind of h t Mal element.
It can be just an h t Mal element or a more specific word in orbit and the same is true for you.
And then here we know the host element will be of type T and D element will be of type U.
And now whenever we inherit from this class we can specify the concrete types sorted we can work with
different types in different places where we inherit.
Now let's all that a constructor here in that constructor we will need a little bit of information we
need to know the I.D. of our template so that we know how to select it and that should be a string we
need to know the host element I.D. which also needs to be a string.
So did we know where to render this component.
And I also want to get a new element I.D. So do we get an I.D. that has to be assigned to the newly
rendered element.
This however is optional which I signal by adding a question mark after the parameter.
The alternative would be to also accept on the find here as a type.
But I'll just use the question mark.
And now with that in the constructor we can basically get this code here and put it into our constructor
of the component class sort of restore the template element.
But of course now the I.D. which we're getting here is that template I.D. which is why I'm getting this
as our argument in the constructor and for the host element of the idea here of course is our host element
ideas like this all is important of course regarding casting here we know this will be of type T because
t here is this generic type which we store or which we use for our host element.
So here we can cost it already and with that we're selecting elements we can all grab more code that
code here where we import a node and so on and where we set the I.D. we can grab all of that.
So let's copy that here and add this to the constructor of the component class as well imported node
then we said element and element here has this generic type you.
So when we cost here we know it will be that you type here.
So we should cost it to you.
That's a good use of generics here which makes this component class really reusable now regarding the
I.D..
This is what we get here.
The new element I.D. Now of course we might not always have this because it's optional.
So we should check if we do have it.
So if new element I.D. is a thing and only if it is a thing only then I will try to assign it otherwise
we don't try it because then we have no I.D. to assign well with Dad we have the constructor.
Now let's use the attach function here.
So let's copy the attach method from one of our Robert classes and add it here as a private method in
the component class
we can then also call this attach at the end of the constructor of the component class.
Now here we want to add an element but we don't know where it should be added.
So that's actually some extra information we should fetch here as a form of argument than a constructor
insert
at start.
Could be a name and that is a boolean let's say and we should move that in front of our optional parameter
optional parameters should always be lost because people might omit them.
You're required parameters start for can't come after these optional parameters and insert that START
is then forwarded to attach their insert at beginning.
You could also reuse insert at start.
I'm just using a different name here to avoid confusion is received as a boolean.
And then here we check if insert at beginning is true if it is then here we have ofter begin.
Otherwise we have before end now we're flexible regarding how does gets inserted.
I also want to mark this class now as an abstract class because people should never directly instantiated.
Instead it should always be used for inheritance.
So in front of class I add the abstract keyword.
This makes sure that now we can't instantiate it.
If we would tried to do so.
Types could would yell at us.
I will also add two more methods and let's see configure method and also then the render a content method
and I will add it as an abstract method which means to concrete implementation is missing here.
But we now basically force any class inheriting from component to add these two methods and to have
them away lable I'm just adding this here so that if someone else looks at our code he or she can get
a good understanding of what the idea behind the component clause is that it does all the general rendering
or the attachment of the component but that the concrete content and configuration then needs to happen
in the place where we inherit side note you can't have private abstract methods so private has to be
admitted here.
That's not allowed by typescript we'll end with this we can extend component here on the project list
and now get rid of these free properties.
We keep the assigned projects because that's specific to the project list.
We also now want to specify the concrete values that should be locked in for our generic types.
And we know if we revert this we know dead will have a h Tim Al Dave element and a h to element.
So here I will pass in H Tim l div element and H Tim l element like this and then get rid of these free
properties in the constructor.
We now don't need dad here but instead we need to call super at the beginning to call the constructor
of the base class and queue that we need to pass some information to the super constructor we need to
pass some information.
The idea of our template element the host element idea whether we want to insert this at the start of
the host element and potentially the idea should be assigned to the new element.
So here's our template idea and with that we can get rid of this here then here the host element that
idea was app so we can get rid of this.
We keep the assigned projects because we still need that here.
We get rid of this year but regarding the idea for the new element I want to pass that as a fourth parameter
actually.
The third one is where this should be inserted.
And here we used to insert this before the end.
So actually what I want to insert here as a parameter for the insert at start value is false because
it should not be inserted at the start but at the end.
Now I certainly still want to set up my listener here.
I don't need to call attached though that will happen in the base class and the base component.
I will call render content though.
And here we shouldn't use this type but just type because we can't use this before Super finished running.
That's no problem though because we receive type as an argument.
No you see I still get an error here because we have an attach method here in project list and that
clashes with the attached method we have in the base class.
So let's get rid of this attach method here.
Now we still get an error because you see render content as private here but we specified as a public
method here.
I would love to have it as a private one but private abstract methods are not supported so I will remove
the private keyword here and now is that we're left with one issue here that we're not having that configure
method which have promised we have here.
Well let's add it.
So here besides render config we can add configure even though I'm not doing anything here.
Alternatively you could convert this year to be an optional method by adding a question mark then you're
not forced to add it here I will added Because we could also argue that we for the project list put
Dad code where we set up our listener here actually into configure so we can reach out to configure
and then do our thing here.
That listener setup and now we should just make sure that we call render content but also configure
like this in case you're wondering why I'm not calling configure and render a content here in the abstract
class in the constructor.
Well we could do this but we might have a problem that if we call this in the into component class then
we might call a method in the inheriting class.
So in a class that extends component we are render content or configure relies on something where the
constructor of the inheriting class actually maybe set something up only after the base class constructor
finished which render content and or configure rely on.
That's why it's safer to basically make sure that the inheriting class has to call these methods instead
of the base class calling these methods for us.
So with that we restructured the project list class to take advantage of inheritance and of our shared
logic.
Let's do the same for Project input now there.
We also want to extend component use the generic nature of that and there we have to age to meld Dave
element for the host element and the HDL form element for the element which gets rendered with Dad we
can get rid of these free properties here so let's do that.
We keep these free properties of course because they're specific to project input.
We then have to call super here and to super we pass these ideas off the template which is project input.
The idea of the host element which is app insert before here is true.
Because I want to insert that newly created element at the beginning here for this project input class
and then a new element ideas.
While that here is user input so we should all go forward debt was this we can get rid of this code
of this code.
And of all this code here actually of course keep this code here.
However we could also argue that we put this into configure maybe.
So let's go down to the configure method which we already have here and add our listeners here or our
properties set up here to configure of course let's get rid of each attach because that's now something
the base class does for us and let's check what types code doesn't like of course we should get rid
of to attach here.
And yeah actually one thing TIBCO doesn't like it now complains that these fields do not get initialized
in the constructor because it doesn't understand or doesn't check that configure is called in a constructor
and dust is initialization.
So to satisfy typescript I'll actually move these initialization back from configure right into the
constructor.
Technically the result is exactly the same but now typescript won't complain it will complain however
that we do have a private configure method so justice before we should change this and turn configure
into a public method.
Now it's not a must do but it's kind of convention to have your public methods first which is why I
will move it up above the other private methods here.
And of course now it also complains that we have no render a content method.
Now I will add one just because we need to hear we're not doing anything in it so technically it's not
required but now we satisfy our base class side note render content and configure in the project list
class can also be moved above that private method here for the exact same reasons for this convention
I just mentioned and with that we also restructured project input to take advantage of inheritance and
let us D.
Based class do a lot of the job.
Let's see where dad now all works if we saved added compiles without errors.
Seems to run fine so dust is work is the question.
And Dad looks quite good.
It works the same way as before but now we have cleaner code where we take advantage of code reuse which
thanks to inheritance.
Now it's not the only place where we can inherit.
I want to conclude this lecture here by also refactoring our project state.
Technically there we don't need inheritance because we only have this one single state we manage in
his entire application.
But imagine a bigger application where you have multiple different states.
One Florida user state where the user is logged in and so on one for the projects one for a shopping
cart.
Now you will notice that some features of your state class are always the same.
Specifically that array of listeners and to add listener method.
So we could all use a base class here.
We could use a class state here and that class has a listener's array and that class also has an add
listeners method.
So we'll cut both from Project state and add it to state.
Now that also means that we of course don't know whether our listener will actually return an array
of projects.
So actually here for this function type I also want to have a generic type actually so that we can set
this from outside.
We can do that we can write a generic type like this here a custom type which is generic we can add
the angle brackets after our type name.
Use an identifier of our choice and then reuse that type here.
Now we can make state generic we can use the same identifier because it's a different construct than
our custom type.
And then here when we say that we want to have a list of listeners we have to tell typescript which
generic type the listeners use for this state object we're creating.
And that simply means we can forward our generic type here and here someone we now extend state we have
to specify the type of data.
This state will work with and instead of states this then gets forwarded to our listener custom type.
That's the idea.
Now how do we use all of that.
Well down there in the project state class we simply extend the state class and now provide a value
a concrete value for that generic place holder.
And here this concrete value is project because this project state is all about managing.
Guess what projects now the private constructor here has a problem as you can tell because we're not
calling Super while we should definitely do that.
Let's call super in here.
That's all we got to do their end here if we scroll down where we go through the listeners we see listeners
as private and it's private and our base class.
Now that means we can only access it from inside the base class but you learned about a no access modifier
which is similar to private but also allows access from inheriting classes that would be protected protected
means it still can't be accessed from outside the class but it can be accessed from any class that inherits
with Dad.
Let's save all that should compile just fine and let's quickly test this and that's looking good so
that works.
Ask before but now again with a bit nicer code.
Using inheritance and generics also for our estate management.