Nx After Dark: Implementing an Angular feature library

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hello it's after dark it's actually nx after dark and uh welcome we finally managed after a long night on my behalf i finally managed to finish the data access layer for the first feature so today we'll be looking into generating an angular feature library using nx we're going to need some more parts later but i want to get the feature library in in place first and then we can start to later look at something like workspace lint rules like um lint rules for boundaries between the architectural layers and something like a shell library for our application but first let's put a feature library into place and then we can have an easier time discussing how to make a more structured approach to to an angular workspace hello jordan nice to see you how are you doing okay we're still working on this energy insights app and uh we're getting close now i think we have the htp client in place at least we merged the pull request for that and we have the data access using the state management using the index component store which also manages the side effects for loading the data thank you jordan i'm happy you you like these sessions now my problem is i'm running out of stream time on my free stream yard subscription so but yeah it's pretty the licenses are pretty expensive so i don't know really what to do if i hit 20 hours i'll have to wait until the 16th of june to start streaming again so that would be a shame okay so we we uh what we're trying to do is we want to visualize data like this uh something like this the co2 emissions on the electricity grid and denmark for the coming the current day and the following day because that's where we have forecast data available as we can see now there's still some good wind not as good as yesterday in denmark but we're just below 80 according to the forecast 80 grams per kilowatt hour produced 80 grams of co2 equivalent emit emitted by the power production but as soon as we hit 3 o'clock there will probably be close to no wind because then it'll be more yeah there will emit more pollution more greenhouse gases into the air right now we're at 47 uh wind power because there's no solar when it's dark and as we also can see here on the live map we are producing uh 1.2 terawatts of wind power and there is actually what is this like 900 megawatts of regular traditional power plants they're using coal and some small ones are probably using natural gas so of course we want to stay clear of those but it depends on the weather and now we have no sun because it it's night and uh when this is blowing but seems like that it's going to stop according to the forecast right let's look at our exchange with other neighboring countries we are importing a lot from norway we're also exporting more than that to germany and netherlands and also exporting here from eastern denmark to germany but we're importing a lot from sweden as well 1.5 gigawatts so denmark is kind of a connection hub for between the nordics and the continental european electricity grids so we're always expanding our capacity in our high voltage grids okay let's go to the code let's go look at the code we have this workspace it's called energy insights it's on public open source on my github repo we have our github workflow that we set up initially for testing building and linting the code we have an angular 12 app but we didn't do much except we extracted some root level libraries so that we are left with a tiny what i call a tiny angular application project now there's still something we can do here but uh that'll be for a later episodes so what do we have here these are the root level libraries i was um just discussing the assets environment styles libraries and in the co2 domain we have now this data access library and it is exporting a co2 forecast domain interface it should really be in its own domain library we'll look at why later when we have some more libraries and we're also exporting the co2 forecast store there are more uh classes in here like especially this uh this service the htp client for for this public data set but that doesn't have to be public publicly exposed to other libraries it's an implementation detail about this data access library because it's being used by the co2 forecast store which is using ngrx component store to for its implementation and it just has this one public property called forecast dollar that's an observable that components can subscribe to and as soon as it's initialized the service it will trigger this side effect of initially and then every minute fetching new data through the http client so that's where we're at let's have a look here at the dependency graph using nx looks like so so as we can see here we have some disconnected libraries right now these we're going to manually attach to the app project later and if there's any feature library depending on them they won't be right now because they they contain static assets static files like images and style sheets so there's no typescript file source file referencing them so nx is unable to figure out that the app library actually depends on these two so we have to set up that dependency that connection or those connections uh we'll we'll do that later once we have start working in the app again and this is what we have been working for for a while as well this is the data access library for the co2 domain and then a utility library for date times we introduced the luxon date time library with its three types the interval the date time type and what was the last one not something we've used yet but there is a third one uh can't remember right now but yeah we this will probably be become a shared library later but we should or we can choose like i've done here like keep it as local as possible at first until we're actually starting to reuse it and then we'll also get better at moving libraries around and see how that works and looks like with nx so what are we going to do today we're going to make the the libraries that are going to connect the data access library to the app library or the app project rather so that's going to be a feature library maybe there will be a ui library as well but definitely a feature library which will sit between data access and the application and eventually we will probably even have something between the feature library and the application project okay that was it for the overview i'm also still using a wallaby js a paid product it works for i'm using vs code but it works for all major uh web editors like webstorm also and atom i guess and yeah it's really something i highly recommend i've been using it for for many years it's my tool of choice it gives me these quick inline feedback on tests and it's really fast at keeping them running and keeping them hot in the background um so let's close all this down uh let this let us generate a library we're using the now all angular package we're using their library schematic to create an angular library it will be called yeah what should it be called uh feature so we're using the feature prefix to indicate it's a feature library and then we'll be called it's called forecast because uh it will be in the co2 grouping folder so it's the co2 forecast feature library that's the way this works so we can see here this is the dry run so that means nx next console by the way the extension i'm using here is uh running it without creating the code but creating the virtual file tree behind the scenes so i can see here this will create a files or a folder called feature forecast inside of the co2 grouping folder inside of the libs root level folder these are the files that it's going to create a lot of configuration then this public api file called index ts which exposes classes and values and functions to other libraries in our project and then it's also generating an angular module and i recommend keeping this one for a feature library so we'll see how that what that can look like it's also adding configuration to package.json i don't know why actually must be a bug uh but we'll figure it out workspace.json will have a project entry with the targets the the bill no not to build the test and the limp targets for this library nx json for the tags we're going we have to remember to add as well t is config based json that is going to be the path mappings which will define how other libraries can import from the entry point of this library and the entry point is this index ts file what else oh it's adding a recommended extension to vs code uh extensions json i think it already did that just config yeah so it's also updating the root just config because in the in nx workspace that just config in the root will list all the different gest configurations in the projects we can also see here an overview of our projects and now i'm starting to notice again that they are not sorted alphabetically which is why i usually add a script for that we'll do that some other day um but here we can actually go for example the data access library we have created you can see the targets here so we could run the test or we could run the lint task or lint target rather for this this library same for the app but it has some more options and including the different configurations that are available here production build development build production serve the development server and the development build using the dev development server from webpack so yeah this is where we're at and uh looks like this is exactly what i i want now i just have to remember to add some tags to this library so let's do that we're using the energy prefix for the energy insights app so that will be the prefix of directives and components and down here you have strict by default strict ts configurations typescript configuration and strict angular compiler configurations especially for the strict template type checking so let's add the tags that's the third thing we need to add here other than the name and the directory so we'll have a scope that is co2 and we'll have a type of the library which is a feature we can add any tags here and we don't have to add these tags we'll see later why they come in handy these tags because then we can add workspace lint rules defining how the different layers can interact and the domains um so yeah this should be let's generate this library now the forecast feature the co2 forecast feature and here we see it in the project overview and we should be able to see it here as well in the explorer here it is and i wonder what it's trying to install i have a sip of water excuse me okay okay ah let's quit that it should be fine these are the changed files let's review down here didn't change anything in package.json ts config base json this is where the path mappings are see it added this entry stop that so we will move that up here so that bit sorted alphabetically that ngcc always causing trouble and here's our project where is it here it is and i also want to keep this one alphabetically sorted and i'll add a script for that later this will help me out for example in the nx console to find a project down here uh but we could also use the run targets here so i could for example say i want to test a project and then i can filter this is a good way um i wish there was a filter here because at some point we'll end up having many many projects at least the alphabetical sword will help because they're prefixed with the domain usually in the project names okay and finally let's look at the root just config and this one i will sort manually for now but let's look at the readme file so this is the co2 forecast feature i don't really want to add anything any description to that well just like this is for internal use um but yeah i don't know you could add whatever in here if you're a big team or multiple teams work in this repo it might make sense to add some more here uh maybe even a public api reference or something like that or at least the description of what's going on in this what can you do in this library okay okay seems like that's good for now yeah and the index ts file stop that ngc the index.cs file here is exporting this feature angular module and the only thing i'm going to change here is i don't want the common module and let's also get rid of the imports we can actually delete all the options all together so it's just an empty decorator factory here with no options passed good so that's our commit generate co2 forecast feature with that let's have another look at the dependency graph now to see how that project turns on here it is so that's here it has the scope of co2 and the type of the feature it's a feature library and now we want we we're going to well we're going to implement it and then we will see how nx is able to detect that it's it will be connected to the data access library which it will depend on and we're going to use it in the app project so that's going to depend on this feature library then we'll start to see our layered architecture here all good leading up to some actual code now and what do we need what i want is um well we're going to get this time series and of course i want to display that somehow we could use a table we could use a chart um so what what should we do first we could create a very simple table because i'm going to use ag grid for both if i wanted and a table but also it has a chart library there's a community edition of aj grid that i want to try out i haven't really used ag grid before but looks like it's very mature and it keeps uh coming up in in our analysis uh for different uh companies uh so yeah i'm going to use that but first let's just try to make a simpler implementation um maybe just a list to to see that the data flowing in and being updated then we're going to add a g grid so in a feature library what do we have here in the feature library you're definitely going to have some what's known as smart angular components uh it could be a page component could be a container component as most likely there's going to be at least one routed component and those are all examples of smart components so we could use the nx console that generator for our generators to add modules well there's no nothing being listed here but there are yeah i guess i would have to if i want um angular's own schematics to show up here let's let's do that for fun we're going to add to the development dependencies add schematics forward slash angular okay pnpm is unhappy i must have messed something up when i was upgrading it earlier or the log file is maybe old or something oh by the way why didn't you tell me i pushed something to the main branch that's bad practice we're going to use a feature branch so luckily i haven't pushed this i'll roll back the latest commit and then we're going to branch out from the main branch add that commit again push the branch to github and you know what i'm going to do uh go into debugging mode here or troubleshooting mode delete the node modules and then the log file and give it a fresh start that's you have no idea how many issues that is for that use usually fixes things so deleting the log file and the node modules and doing an install again and luckily pnpm is pretty quick even though my internet connection is relatively slow these days for some reason okay while we're waiting i just got a message from uh craig who's creating the nx.net plugin says that he's been working here on the docs so looks good congratulations on that craig uh let's look here okay there is a dark mode let's disable this dark reader and use the actual dark mode looks similar okay docs using uh docusaurus i think there's an nx plug-in for that actually uh okay nx.net core nx doc linux.net typescript why is there an nx doc generate docs okay interesting i'll have to try this out at some point yeah so in an earlier episode i was um i think it was actually the first one of nx after dark i tried it out nx.net and it's it's really great even as at this early stage i didn't find i i found a few issues and gregory uh fixed them like within the same day before i could even yeah i said on my live stream that they were issues but he had already fixed them so that was great i'm using.net at work and have been using it for many years along other programming languages [Music] so yeah i really it's a better it's already a better experience than the.net cli itself because you have to remember all the commands and run them manually i like this that you can use the nx console and then you get the dependency graph and you get smart builds and smart tests and so on so yeah a great project if you're into net this is worth a look and as i mentioned i have a a video on that in in this youtube channel okay pnpm is done uh updated something so let's log with the dependencies and just for good order i'm going to restart wallaby so that it doesn't have any issues where did it go well let me console did i not start it again maybe i didn't no okay here it is starting up starting the wallaby app in the background and should be running the tests yes here we go and now it's keeping them hot all passing good okay so i wanted to install the schematics for angular because now when i use nx console to generate i will also see all the angular schematics that are included by the phone so now there's one for modules there's one for components and so on and the good thing here is now i can see visually all the options which makes it easier to make set defaults in my let's see that's in the workspace json at the top i have my defaults for generators as nx calls it generators angular calls it schematics same thing basically and i already have a few defaults here for i don't know why it keeps adding this normal angular component defaults because there is no such thing there is not a component generator in the normal angle angular package okay so we could use this for generating modules and components but i i'm so used to doing it all manually so i'll probably be doing that okay first thing we're going to need is i am using the model view presenter pattern so i'm doing container components and presentational components so first thing we're going to need is uh some sort of a container component so i'm going to use single file components so i don't really need folders because there will only be one file and maybe a test file as well so let's call this the co2 forecast um component or let's see container maybe call it actually you could forecast container container but sfc for single file component and here i'm going to make it a an angular component and name the class co2 forecast container this is really what i want by the way hmm yeah that's good for now can change it later we're going to need a selector and it will be in our g forecast also need change detection on push we will have complete and it will be an inline template even our styles will be in line for example well we're always going to start with post play block but we're actually also going to make view encapsulation and make it let's make it none or view encapsulation but not from angular core all right selector view encapsulation wrong oh it's just called encapsulation for some reason anything else no not for now not for now okay we should end with the subject suffix component okay call it container component okay now you're happy good one last thing we're also going to add the module here so it's going to be a single file component also within a scam a single single component angular module we'll call it the co2 forecast container scam and it will declare this component that's why i'm putting it below because it's going to refer to us above it's going to export and not if you wanted to route it but in the initial version we might not add want to add the routes for now so for that case we're going to export it instead exports probably going to need some imports and since this is a container component we're going to use probably the async pipe so we're going to need the common module for that and that's it that's our starting point here in a single file we're going then to export that module that's scam co2 forecast container scam so this is this feature module is going to be forwarding the same exports as this scam has so that will be one component that's the whole purpose of of a scam good what is it complaining about appears and exports but itself has issues no there are no issues what are you talking about probably just angular language service being weird yeah this is our starting point uh here we installed the schematics put that in a angular schematics put that in a separate commit now write that co2 forecast container components there we go and yeah so technically it might be a good idea to also export the component since it's a component that might show up like you might want to have the type in in other libraries but also let's wait until that's needed let's just keep the module for now as an export so what do should we yeah we could add it to the app already so we will delete all this main content here keep the rest for now uh whatever do i have left flex header main going to remove most of this this one for now energy insides title we have the nx logo welcome to energy insights then let's oh let's let's organize this a bit yeah so i'm actually going to here in this component file i'm going to create scam for this app component it's not it doesn't need to be exported but this is where we're going to import this container scan was called like so component scan see if it can auto detect it can't okay uh it's typescript server not updated right now and we'll do it manually energy insights feature forecast oh oh we don't have access to this scam yeah okay this will be the entry point this this scan this container forecast container is the entry point of our app and we get access to that using this feature angular module that's what we're going to import in here instead but now this app scam we're going to we're not going to declare the app component here but we're going to import the app scam and the leak providers we'll scrap up here and we're good and now we should be able here in our app template to use the nrg co2 forecast that we call it co2 forecast like so and let's restart i don't know tia server maybe should be picking this up let's try to build it or maybe just serve it and see if there are any issues because it should be good at this point oh the angular compatibility compiler okay good to see you jordan see you another time so it looks like it is good here's our app con there any errors strange strangeness he's not happy about something ab scam module appscam declarations exports um do i need to export it now no that wouldn't make sense only being bootstrapped hmm that is strange so is it not happy about the scam here maybe not some reason that would be strange let's try it here without an app scam see what happens okay that was not the issue what is going on angular energy co2 forecast energy co2 forecast why does it say that i'm having issues here in this one i don't understand angular are you putting limitations on me i will get angry with you let's externalize the m to separate file and and also the boring module suffix so we have no idea which kind of module it is here and the feature module let's refer to this new module which is a scam all right still failing okay what on earth is going on if i leave out this co2 forecast component what's going to happen will it render nope okay but if i remove this forecast feature module what's going to happen still okay so is something messed up in the app component in its template or something i don't know i'm going to have to roll back to the app project to get hopefully a working state that is so strange um okay so this is the generated approach okay so that works that works so when will it break let's keep it over here with our live reload and now i will remove all of this main content still happy good then i'll remove some styles that we're not going to need anymore feel good yes okay changing the title sure some of you can have spotted whatever i did wrong earlier hmm now let's temporarily stage this let's go into let's try again this of creating an act an app scam that's how i like to roll and i still don't know what i did wrong and exports imports and we need this co2 forecast container now into the co2 forecast feature or something uh remove the these paths they're also not the right path maybe that was what's going wrong it should be imported from the feature module [Music] forecast okay declared by more than one energy module yes that's right we'll fix that here we go fail to compile why start over with the development server ah here we go so probably it was just the development server being confused by me changing the group module around okay so now we can rename this one to be the app.sfc for single file component and update this path here as well but very good so now let's go out here yeah let's maximize our editor again it's really hard to work at this high zoom level and since i only have a free stream yard license i only have 720p so i really have to have it this big for you to be able to see it somewhat clear okay moving this inside of the single file component class and renaming it to this well a scam container scam and referring deleting this separate module file referring to it here in the feature module like so yes okay now comes the question can we add it to our app nrg co2 forecast something is going right i probably didn't add anything to that container template did i know here we go there it is let's get this committed um yeah this is our commit good good finally starting to work [Music] now now what do we need okay so this is this this will actually be the scope of providing our uh what's it called the store and we'll use view providers so that it's not shared by any content projected um components it's more of a it's a narrower scope co2 forecast store will be provided here so every time this container component is instantiated the co2 forecast or an instance will be created and when this component is deactivated component store will also be shut down destroyed so that should also disconnect or unsubscribe any observables and subscriptions and so on oh prettier you really like to tell me how to format everything don't you [Music] okay okay now we have the store what should we put in our template we're going to need a presentational component and then we will provide it with the data so next up next up creating the co2 forecast single file component let me even yeah that's it i will copy paste this one but call it due to forecast scam co2 forecast component and it shouldn't have a provider and let's call it ui and this suffix here because it's a presentational component oh this import is all wrong should be the data access there we go back to the presentational component here we go no imports for now but now we can use this inside of our container to forecasts did i rename them the scam yeah i did that's what i need when i import that now i can use it in the template right here energy forecast ui good let's look at the view yeah still co2 forecast so let's look at take a look here in the element browser we have our forecast container and we have our presentational forecast component which has this title right now okay so add co2 forecast at presentational forecast component here we go let's push some commits now what do we need well now it's time to think about which inputs would we like in this presentational component this is where we we're going to need that domain object or something similar depending on well the presentational component should think about what would be the easiest for me to display and domain objects or domain structures and interfaces at least should be something that's easy to use but in some cases you would want for example the container component or store and a component store or something like that to map it into whatever yes maybe here we need some special data structure for the whatever chart component we're going to use in this case from the ag grid but i don't know what that looks like yet so i'll start by accepting a forecast yeah forecast and now i need the type right so i want to see a two forecast here but that is not exported by our library and in fact it's it's located inside of the data access library this is not where we want it i mean we could just export it and we might do that for now but think about this for a second this is a presentational component and in some cases we might want to split this into a feature library and a ui library for the forecast which has the presentational component and a ui library shouldn't depend directly on the data access library so if we pretend that we do have a ui library containing this presentational component then it wouldn't be allowed to import from the data access library so that's not a good place for this domain structure and also i'm not very happy about this property name um and in fact it's like it's marking it it's only one date time it's not the interval of luxem so it's not really a good representation of what it is this this data point because it's actually representing a period in time a five minute interval in this case so a start point in time and an end point in time so it should really be an interval uh so yeah that's that's something to think about for now let's move at least move it this domain interface and the collection type outside of this data access library so that if this presentational component was inside of a ui library it would still be allowed to refer to this domain class so let's generate another library angular library call it what should it be called it can just be called domain uh so but it it's inside of a co2 domain grouping folder so it's the co2 domain library and let's add some tags here and the scope will be c co2 the type will be domain it will only have the main types and domain classes maybe probably not but interfaces and types of enums and data structures those kind of things generate this one and now we need to go through the whole checking up on whatever was generated let's close these down so now we have the domain library here let's go to the readme file co2 domain library and let's go look in here and ps config base sort these um we're sorting the path mappings here alphabetically and in the jest conflict also sorting alphabetically so and just one change i don't want to have here is this one this is from the other the feature library so generate co2 domain library shut this down and what are you changing here in this lock file what i haven't why why is this happening stop doing that oh i is the generator for the angular library messing up my pmpm node modules install when it's not adding any dependencies that's really annoying now it has to recreate node modules again oh well okay so we got our we have now our co2 domain library so let's pull out this co2 forecast interface and collection type move it inside of here delete the folder it came from then delete that auto generated module we're not going to need an angular module inside of this domain library and in the public api the index ts file we will export everything from co2 forecast okay that is good and now the files that were referring to that forecast try to find them here youtube forecast not there anymore not let's restart the tia server which we usually need after generating a new library and then we can import from domain co2 domain co2 forecast good are we referring to it in this file nope okay pmpm succeeded now there's no changes good okay okay okay okay everything what to change here that was probably just some formatting i don't want that and i don't want to change here in the forecast component but the others here ah a little that's to see if there's other files um referring to that co2 forecast interface from the old location and let's also run the tests i should wait until ngcs is done i hate that here we go okay let's also run it skip nx cache just make sure i have to do double dash with the npm to forward parameters to the script okay everything good oh wait okay so it's actually just running so i'm running all the tests it's only running for one project so we should do run money target test parallel that's good and luckily i would want max parallel of i have 12 logical cars so i could probably use at least two thirds um or at the very least half but also two first should be good but that might not be good for the ci by the way am i using this script for a rci workflow that's not good that's not good at all actually uh test pmpm test wow this is bad because this might have only been running yeah for that one app project so not for our other projects that is not good at all okay so what what would work parallel for the ci i don't know should we should yeah fix this later uh here from the target link parallel okay ti fix test and length and then let's run it locally here okay let's see what's going wrong all our project okay so i forgot something fun many uh forget lint and say all let's try the pnpm test command now locally okay so now it's running all the tests and hopefully they're all working or i have really messed up in previous episodes phew good thing let's also try the lint so this max parallel is i think it's three by default that's not really good use of 12 cores but on the ci server 3 is probably a good number so our lindsinger here right so there's actually an error here because this should be importing locally or relative now where's that from we're in the util date times so where's the zone okay it's probably here oh good thing if we fix that good thing we fixed the ci here okay back to what we were really trying to do import go to forecast um so this seems to be the only import okay so we can say who co to forecast the domain library yes the public api is now exporting that very good very good so now in our let's close all this and open our co2 forecast component stop that i'm really missing out my keyboard shortcuts right now uh go away no really go away co2 forecast sfc single file component okay now we can import the co2 forecast interface from the domain and we're using strict settings strict angular compiler settings so it's not really happy about the fact that we're marking this input property as a ceo forecast but we're not initializing it so at some point this might not be technical correct or it isn't so and we shouldn't just be making up something here that that wouldn't make sense but since it's a collection class actually we could do just an empty array and we're good this is one way of solving this issue but there's another issue that we'll like to see in a moment when we can use this input property in the container component so to bind it okay so forecast and then let's uh let's loop over the forecast here let's do table and row well start by table header and inside of here we will have a table dimension or cell one for [Music] or time end time and one for let's say price area and finally one for and actually added a second column here one for the co2 mission rather co2 grams per kilowatt hour technically it would be more proper grams of co2 equivalent per kilowatt hour so let's use that this is our table header and we'll have now a table row i might have messed up the names like is it is there t h or something yeah what's the difference uh i have to look this up it's been a while year old html friend and beyond the th element and an example gh okay yeah so we should zoom in should be using th instead of td in the header but there could even be a th for every row if you have an advanced table like this one but yeah these ones should be td instead of th and we should actually wrap them in a table row page for table header and here we're going to have uh three times td cd so i don't have emmet completion change manually then and we're going to loop over using ng4 and to use ng4 we're going to need the common module we're going to loop over let data point of forecast then we're going to say first column here will be in a point that minutes five utc and then the date pipe let's just do oh this is a date time which is not this is the date time from what's it called luxem so this is not supported by the date pipe so what could we do i really don't want to i mean okay so as a first step it will could be all right to say convert it to the date instead that would be to just date then we can pass it into the date pipe that's a good first step but i really hate having logic in the template like so second cell data point dot plus the emission and we'll pass it through the number pipe and then we could format it like uh what's the i have to look up the parameters then let's do that number five it's not called what's called the decimal type but the name is number yeah digits info see more okay so minimum insert integer digits yes one minimum fraction to maximum fraction okay so we would like at least one leading digit and then two two decimal points and this should be a string so we have to do like so good and then the third cell of each row we have a data point and we're taking the price area okay okay and now let's um we have two things we could test it as it is right now or we could connect it to the container component let's just we already have the data or hopefully if everything works so let's try that out first in manual testing in the ui just to see so here in the template of the container component we're now going to bind to the forecast input property and we're going to give it our forecast dollar syllable profit property pass it through the async pipe and now we have two issues we don't have this property and because we're using async pipe our input parameter has to accept null as a value because the async pipe will always initially emit a null value so our input property has to support that somehow or it won't be yeah strict template type checking will complain like it does here okay so first let's get that property so we will let's define it first it will be called forecast dollar finish notation and it will be an observable of a co2 forecast remember that domain collection type so a co2 forecast is a read-only array of co2 forecast data points okay where should we get it from well let's inject our youtube forecast store and should we call the store yeah youtube forecast or and remember this is provided in this container component so it will follow the life cycle of this container component now we can do co2 forecasts let's see you i guess i'm not picking up this forecast oh well it works now this is an observable of the co2 a co2 forecast good so that eliminated one issue and now we have this we can't pass a null value because that's not defined by this this input property but async pipe is always emitting a null value initially um so we could also i mean either we have to add null as a value that we accept here in the input property or we do something really annoying like ngf forecast dollar async as forecast and then instead of using async we can do it like so that's another option and the downside is now uh we have that con conditional rendering in our template and there's a few other issues with with the async pipe as well like how would you how do we handle errors uh how to hand a completion of an observable and uh what if when we're using ng if what is this what if this value was null what if this value was false what if this value was any other type of falsie you know what this is an okay solution for i mean really we should have a better uh option a better option could be using a lead directive or a push pipe and lead directive would be good it is available as part of the ngrx component package but it's not recommended for production usage so we could look into the rx angular template package instead where it also is in a more advanced version that has other options and use cases and optimizations but for now let's stick to common patterns yeah so let's stick to the angular packages for for this solution for now this should be okay so the downside is that this component won't be rendered until we have data in this observable um that's actually not good like it would make sense to start rendering the chart immediately and then when data becomes available it will be passed on to the chart so let's yeah let's actually use look at some other options here rather than having ngf let's go back to the async pipe solution like so so how would we accept null here or we could say co2 forecast or null and now we're good but now we have to make null checks every time we're using that forecast for example here why is it not complaining should really should really tell us that something's wrong here like what happens if it's null okay if we wanted to do it like this way i suggest we add uh either we could add a setter or we have to add a center and then we have to add header as well and now we have to keep the same type and we have to add a backing field and i rather than private i actually prefer uh to use the private fields from ecmascript um forecast this should never be null but we can initialize it to the empty array and this is what we will return from a getter and in this setter you can do this that forecast is and assign it but now we have the issue right what if it's a null okay so one thing we could do is we could say forecast is assigned to the array if it's knowledge so if it's null or undefined then we can we will never have null here this is one option it's a lot a lot of code just for accepting null and if we have to do that for every input property it will get a bit annoying right but this is a actually a proper solution for this issue of accepting null because of stupid async pipe um another option is what's called input setter type hints um so here we also have a backing field but we will eliminate this null so that when we're using this uh oh by the way i forgot to do this so we if we eliminate the null type here now when we're using it in the template we don't have or other places we don't have to do null checks but now we have the issue that the types are not aligned between the getter and the sitter but if we remove it here now we have the issue of the async pipe again let's look in the container template here null is not value valid in this context here so another option we could do is we could have a static property called ng i think it's nv accept input type then underscore and the name of the input property which is forecast and then give it a type the time is then co2 forecast or null let's now see in our container now the issue is gone so i spelled it right so this is telling angular's compiler it's a compiler annotation like all decorators this is telling it that you're okay to also pass a null in the setter even though it's not mentioned here because now we can make the type of the getter more strict but angular is still allowed to pass in null here in the center so we still have to handle that and we're doing it here with this default assignment on knowledge values so this is um i don't know actually when they introduced this i think it was must have been part of iv so nine or later angular 9 later this is an interesting option of course the issue is that if we're using linters that tell us how what's the order of properties and zone where when should static properties be present we have the issue of they're not really following the principle of proximity this is obviously related to this one well obviously when we know it but it's related to this property it has to keep in sync like the types and the name but if if we have some linter rules we're not allowed to move down the static property here next to the consider that it's related to so this is the downside of this approach when you have multiple input values then they get all get set more and more apart but we already had that issue actually when with the backing field we'll have the same issue uh that they are related in one group by lenders or placed in one group and by lynchers and the public properties here will be placed in another group according to our lin rules okay yeah but um this is actually yeah this is a good solution kind of the best of both worlds we're supporting novel so we don't have any special logic we don't have cons conditional rendering in here and we should be able to handle uh an empty array so very good and simple logic inside of here so we'll we'll go with this and see with that how that works like one more thing now that i said i'm going to use the private fields let's not use the private access modifier here let's instead add a private member like so and assign it from in here like so use before initialization [Music] this whole thing that's the downside here i do prefer the ecmascript ecmascript standard rather than the made up typescript standard um also these private fields private members you can also have methods uh with the hash sign in front of it they are actually private at runtime so no one outside of this an instance of this class will be able to access them so they are actually private not just at compile time which is nice okay let's see what we have here we have now let's let's run the formatter just to make sure here [Music] okay and then we'll say uh display oh some formatting add that in a separate commitment here we'll say display co2 forecast here that's probably hopefully only formatting this one same thing this is a style format commit let's push our commits and now if we're lucky we will actually have a working app come on now oh oh i forgot there was an export in in here okay good catch thank you angular compiler finally doing something useful um remove broken export now do we have a working app let's find out no provider for http client i forgot about that old devil then we have to provide the http client module okay we actually have to add that here in our app module like so and let's just let's run the formatter go back to the app and okay okay we're sending our request and something is wrong might be the um yeah probably the url encoding but we have our table here so that's our presentational component being uh presented or yeah being displayed by the container component which gives it access to the well through the co2 forecast store um we get the forecast which will then the forecast store will look for data our request for data and we do have like a we have a timer right that should trigger after one minute so now the question is does it handle errors here it did it did here it came again with a second request after a minute so that the whole observable flow here is not broken so now we just have to debug or figure out what's the issue here and let's go and see the parameter the query string parameter we have sent here this is the sql query so let's start by looking if if this is right no formatter for sql okay i'll format it manually oh okay so here's one issue our date time i mean this might work but i would much rather it did like the plus here which is a bit odd because i figured in the tests for the sequel generator here okay so we have wallaby so we can actually do a console log of the sql output here see that here it is actually using plus which is what i want for the utc offset and but it was being sent like so and what's the reason for that well i happen to know that this c can implementation which is backing this api considers plus as a space character like a single space so we would have to further url encode this plus symbol i think as so what is the url in code encoding of plus let's find out if we have a plus character and we say use the encode uri component global function and we'll learn that it's actually percentage and then the hex code of 2b so we might have to this is something that angular angular's http client is not taking care of for us so inside let's go back to here to let's go find our http client here it is and we were trimming something right where were we doing oh here sql prim sql parameter but also we also want to url in code um url and code c can well encode and then we will pass it under the plus symbol here it will look like this so that we're not doing a full url encoding because http client from angular should take care of that but additionally we will url encode the plus character here so let's add a function locally here call it url encoder character will be a string and text will also be a string and we'll get a string back okay so here girl encoded character is you are encode your eye component character sure here so this will give us as it was like um percentage to be plus will become percentage 2b here now we'll say this is where we're missing the replace all function because that is coming to ecmascript screen replace plays all yes here what's the support for this browser compatibility it's actually in modern browsers already yeah but the issue is yeah we should either upgrade our library our lib what are they called let's go find it here lip es2017 and there's probably a bunch of these all over the workspace yeah and some of them that's quite funny uh the root one is es 2017 but the rest of them is es 2018 so something went wrong here nx because i used the exact same version to generate all this okay but which version did that come in um string replace all yes and yes probably 2020 or 2021 oh here it is is it 2021 yeah excellent roush meyer is usually good at creating posts on new features in the ecmascript standards so it's an es 2021 yeah so either we we have to do it in every library which is a bit of a shame um so either here instead of 2017 we can say 2021 or there's a way to do it like on a more granular level yes 2021 yes 2021 oh it's not here yet in typescript oh here we could do it individually with the features use 20 20 string let's try that and also go to 2018 and let's move the dom to here and then go do the same thing for all of these places and yeah this is what is generated by nx but now i'm thinking they should work like they're all extending the route so it should be enough to put it here as long as we only have an angle application at least because of course the issue is if you're all of a sudden also having a node js project for example it might have another ecmascript standard according to depending on the version of node.js but since we're only having angular projects we might delete these project specific configurations but then we have the issue of every time we generate a library we have to delete this setting on the other hand now we have to keep adding this um this setting so maybe we should just let's try that ts config face uh like having it one once source what is it called single source of truth right let's find out let's see if it gives us issues then we'll have to remember to remove this lib setting from every generated library okay let's go out to where were we working here url in code character try text replace oh yeah still we have the issue of it's what was in string features of es2020 we should be able to look this up in typescript es2020 string match all okay so if we got this then it's working match all we didn't get this maybe the gs server needs to restart because we definitely have the dom or is this also part of node js i don't know oh but now we have it look at that okay so it's working but the issue is typescript 42 doesn't seem to include vs2021 right yeah what yes next and does it have specific ones string okay let's try that restart the ts over since we changed the configuration waiting let's see if we have the replace all now replace text replace all we do great great so okay we're we'll say now that we're using modern browsers so we'll open up es2020 and in addition he is next to string which is this one he is next that string means that we get replace all yeah replace all there's two um interfaces here two signatures one where we pass it a string or a regular expression as well as a replacement value which is a string and the other where we can pass it up callback as a replacer function here good this is exactly what we wanted but now we're limiting ourselves to modern browsers we could add a polyfill for this but i'm okay with saying we're only using modern browsers okay but now comes the question does justice running on node.js my computer is running node.js and but does the note just then have the replace all option i need to figure out here um which version of node am i running right now 12. i should actually be running 14 since that's supported by at least angular 12 hopefully also nx 12 and yeah i'm using this tool called volta um node for team.x so another thing we can do with with volta is you can go to package.json and we can actually add here a volta convict and say node 14 that x i think and then volta will seamlessly switch between versions of node depending on the project so okay if i do note version right now node oh okay it's not happy about 14x so let's say like so that worked has to be excel what about this i already have to specify the exact version apparently i do um so let's try that node v now it's at 14.70 every time i'm working inside of this project folder before i was on 12 what was it 12 21 so let's just try that see that volta is seamlessly switching between versions of node and if i don't have it installed it will complain okay so let's see say to volta always use node 1417 in this project good so hopefully that is enough hopefully i i actually don't think so but hopefully um node.js 14 has this es 2021 um api we'll figure out when we're testing this one okay so what are we searching for we're searching for the character and we will replace it with a url encoded character turn this and the issue if we didn't have text string replace all method we would have to use a regular expression and we would have to do like a placement better we would have to do it something like this url encoded character b so we will we could do this instead this would work with almost any version of javascript it would be using regular expression so it would actually be a bit slower and also more code and a bit more noise so this is not even right it should be just a character yeah so real encoded character this would work in any version so that that will be our fallback uh if if this doesn't work in tests yeah we're going to add this test if we do that now you're all in code character yes open up where is the wallaby i can't see for the camera here it is [Music] import from url code character [Music] here's the name let's give it a good name afterwards this is what we want to test here so um character plus um text say well let's take a spring or another words iso 8601 the time and then it will be about approximately the current time in the danish utc offset actual text recorded text will be url encode and the character and text here okay now we're seeing this issue here text replace all is not a function so it's not supported by node 14 and just is using node so it's a bit of a bummer because that means we would have to add a polyfill to yeah every you know like all the just configurations maybe we could get lucky that we could add it down here to just preset i think that's called once per test suite or test project so is there a polyfill for this here it is hmm um this is for a url what about here npm packages okay go to npm actually search for face all here it is this is the name see if we can import it here in our just preset of course then we need to install it add it using pmpm come on here we go and now the question does it run open up here where is it there's wallaby try to stop it start it again just preset is invalid okay oh import so this is using require so you it seems like it's the old common js syntax so let's try it this way let me stop wallaby start girl wallaby yeah this is a modern web dev in a nutshell um different toolings fighting over everything okay text replace all is not a function i would think it would be enough to import it let's see here place all shim oh let's try that post replace all replace all gem let's try again wallaby stop wallaby start still saying it's not a function okay so yeah this is not my luck um uh okay we'll go back we'll revert some of this um remove it here because it's not working with wallaby that's my preferred tool or maybe i'm doing something wrong so let's revert to using the old style here please movement pattern erect x appear that character we want to replace and g for global flag and it will be text replace this pattern replace it with the url encoded character and what's going on here invalid regex nothing to repeat oh so when it's the plus sign oh we have to and we have to do it like so then regex so it's a bit annoying because you'd have to do it this way actually and even worse this way when it's a strength yeah okay so let's go back here to our global our route choose config and remove this one and this one should actually also be matching our node js version uh so let's do es2018 so the result should be seven plus we should have to be let me try to restart wallaby here um oh yeah it's not really working with this here i'll encode sql parameter neural income plus man all because of missing that string replace function okay but now it's working great like so put codes and url and codes uh plus character and i don't really i'm right now to do more tests so [Music] let's go into the http client and here is it here okay let's uh what's going on here wallaby oh what's the console nevermind um and let's go and move wait what did i end up doing at this one yeah this will only replace the first one so it's really poor that i didn't make more tests it url encodes all plus characters [Music] um text i'll link out plus six next to b and we'll extract this url encoder plus to here over here and equals four and the url encoded plus plus three plus two plus one now we can see that the implementation is actually not working right now it's not for multiple pluses which is very poor so now we have to go and say well hero encoded plus replace all pattern um that'll look like 2 b g sorry url encoded yes rollback dude i'm messing up url encoded plus and we can do that only one time for this module and yeah this is what we want to replace it with and this is the replacement pattern so every time we have a plus actually all of them we will replace it here we go yeah good so now it's working now it's working like so okay all good do we still have the app running we do let's see what's happening now let's close all of this down and reload the app okay something's still wrong what about the this one let's copy can i copy the the link address and just see what this is looking like where is the here's the time and then oh it seems like it's being double encoded or something okay uh this is not really working out in my favor so i'm actually going to roll back everything except volta so and we're going to continue this some other time because now it's really late um i have to catch some sleep but uh don't worry we'll figure it out next time for now my hair is messy uh for now that was it for nx after dark see you some other time bye
Info
Channel: Lars Gyrup Brink Nielsen
Views: 166
Rating: undefined out of 5
Keywords: nx, angular, ngrx
Id: Qku_EgPUn7c
Channel Id: undefined
Length: 138min 25sec (8305 seconds)
Published: Sun May 23 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.