 Okay, so we are recording. We are live. Welcome to everybody who is joining us today. It is officially December for most of the Western world at least it is the last month of the year. So I'm not expecting as many folks in today's workshops as we have had previously, but welcome to everybody who is joining us today from wherever you are. While you are joining please if you haven't already and you want to code along with me please do get your local development environment ready. You will need a local WordPress installation, a code editor like VS code or sublime, and then the part two block code to the block code that we worked on in the last two workshops, which you'll notice is is versioned version 003. Because in part one of the series I actually ended up doing parts one and two of the code so that got merged together so I apologize for the numbering confusion there. And then if you've got that code please do let us know in the chat where you're joining us from. While while we all get set up. While folks are doing that I'll just quickly introduce myself again for those who have never seen me or met me before my name is Jonathan. I'm from Cape Town in South Africa. I used to write code for a living now I do this for a living. I'm a sponsored contributor automatic. And I'm a sponsored member of the training team so we work on learn.wordpress.org. We create tutorials we create lesson plans for meetups. We create. When I turn my phone volume down. We create these workshops and we host these workshops. And that's what we do. So, I'm going to get going. We're going to be continuing our series of developing blocks without using react. I titled this without using react but we're not really not using react we're using react underneath. But the code that we're writing is plain JavaScript code so we're not using any JSX and any compiling transpiling any, any MPM build steps and like every write the code and it's deployed and it works. As always, a couple of announcements. Welcome to everybody who's joining us again and also welcome and thank you to Leo who's co hosting with me today. Leo is a good friend of mine from Cape Town so I have another Cape Townian in the, in the session with me today. Leo and I met many, many years ago at a word camp in Cape Town. Leo works at a company called codable and he is a member of the community team and various other teams around the WordPress space. I'm super chef to have him co hosting with me today. As always, as always we are presenting in focus mode so that means your video is turned off by default and your mic is turned off by default. But please if you want to please do consider enabling your video if you would like me to see you. You don't have to but you're welcome to. You're also welcome to ask questions. You're welcome to either post your questions in the chat or unmute to ask questions. I find what works is if folks post in the chat. If it's clear then we can go to unmute you. And if your questions are related to what I'm, I'm dealing with on screen please do post them. If they're not related to what I'm dealing with on screen I do allow session pauses for sort of tangential questions. So you're welcome to post them then. Cool. Then as a reminder if you haven't already please do consider taking the learn WordPress learner survey. I'm not going to go through that again. I'm going to do a little bit of a quick tutorial install is ready with plugin. And as always, if I'm going to fast let me know, we will be posting this to WordPress TV afterwards, and there is always more WordPress focus content on learn WordPress. Oh, and I'm going to do a little bit of a plug now. For those of you who joined me for my, my WordPress block development sessions. All of that work is now compiled into parts one and part two of the developers guide to block themes. The workshops have all been compiled into two courses, which you can take on learn WordPress.org. So if you haven't already please do check those out and then send me any feedback you might have. Send me any questions you feel like the courses don't cover around block theming and block theme development, because I can see another course coming out of some of those questions so if you're taking any holiday time or whatever and you want to just work through a couple of courses, you can you can go through these. This covers sort of the fundamentals of developing, developing block themes. But today we're focusing on developing blocks. So let's get on with the show. So just as a note, I usually drink coffee all session long but it's starting to get warm here in Cape Town. Leo and I were just chatting about the ease and Durban I'm in Cape Town and how it's getting hotter and hotter. So while I do have coffee with me I also have water so I'm going to be sipping different things during the courses today. We're going to be reviewing the code so far just for anybody who needs to be caught up as to where we are. We're then going to be looking at what's known as the block toolbar and the block setting sidebar. Now, if you had signed up for the session earlier this week. You will possibly have read in the description that I said that the next thing that we will be doing is adding additional attributes to allow the user to edit the block styles. So what is the plan. However, on Tuesday when I did my live stream and on Tuesdays I do a live stream to prepare for my Thursday workshop. I realized that that wasn't a good plan, because first we need to implement or at least we need to understand block controls before we can use them. So today we're going to be focusing on implementing a block control into our block, adding the block control adds additional architecture to the block code so we need to understand how that works. We're going to be changing some things so we need to fix those things. So this section this session is going to be focused on that and then next week we will do what I had planned for this week which was allowing the user to edit the styles, because there is a way within the block control system, or at least the block system called block supports, where you can say your block supports certain things like a background color text color those kind of things so we're going to look into that next week. And the plan after that is to then do a custom support in other words, the block doesn't support this thing, and we want to build it in ourselves and the idea there is we're probably going to do a background image on our block, because background images into default supports in blocks, but we're hopefully going to be able to build it for ourselves so that'll be a little bit more custom, possibly a bit more difficult possibly split over two sessions I don't know yet. So we'll see how that goes. Anyway, continuing today. So once we've had a look at the block toolbar and sitting sidebar understood what they are and how they work. We're going to then look at adding these components to our block which means we need to learn how to add multiple elements to a block so far we've just added one element, the rich text component. Now we're adding additional components so we need to understand how that works in the plain JavaScript framework. So here the block codes implement the controls, we're going to add an alignment control to align our block content and we're going to see what that does and how it works. And that's, and that's the goal for today. In terms of physical objectives the physical things we're going to do is I say we're going to review the code we're going to review block toolbar and sitting sidebar. We need to the first thing we need to do code wise is update the block wrapper and I'll explain what I'm talking about there. So that update is going to break some of the styling so we need to fix that we're going to look at how that changes in the back end sorry in the editor and on the front end of the site. Then we're going to implement the block controls component and the alignment control components and we'll talk about both of them while we're there. We'll then apply that alignment attributes because we need to store that alignment value somewhere. We're going to update the save function to use the alignment. And then we're going to just very for fun. We're going to move the control from the toolbar to the sidebar and I'm just going to show you how sort of easy it is to do but what it ends up doing and what we need to look at. And then there's a little bit of cleanup towards the end that we're going to do so hopefully we'll get to those last two in the hour and a half that we have. But those are also throwaways that if we don't get to we can we can sort of skip. That's all for today. I'm going to grab a sip of water and need for a break if anybody has any questions. Otherwise, we will kick this off. And I was trying not to gulp that water down hopefully didn't hear any audible sound effects then. Okay, so let's start by reviewing the current block code I've got my default WordPress install set up here. The developer tools open so that I can see what's going on. So those areas I'm expecting to happen every time so it's fine if I see them. I'm using the 2023 the new 2023 theme but it should matter which theme you're using as long as it's a block theme. Actually, no, it doesn't actually matter. It'll be anything because we're going to add it to a post. Plugins I don't currently have my JavaScript block added installed so I'm going to install that now quickly, and then we'll have a look at that code. So I've got it on my desktop. There it is there. I'm going to install this so this is an exact copy of what I linked what Leo kindly linked through for us earlier. And I'm going to activate that while that's activating I'm going to switch over to my code editor. I'm going to open up the block code and make this a little bit smaller so I can see what's going on. Okay, so so far, we have created our block. We implemented a variable which which will allow us to use the create element function from the create package. We implemented rich tech the rich text component last week so we added a variable for rich text, and then previously we also set up a variable for use block props which are using throughout our code. We registered the block type with the block name which uses the slug and the block name. We're passing in the attributes and the same attributes to the edit function and we're destructing what was that props variables so this is the object destructuring a rotation. So it allows us to extract attributes and the set attributes function from the properties past edit function. The content is just used that when the when the thing is changing updates the attributes. And then here is the sort of the most important code where we are returning a new element using the create element function up over here. We're passing in the rich text component as the type, the first property. And then the second property which is the properties of the rich text. We're assigning block props to it and then adding some additional properties like the tag name on change and the value. And you'll remember from last week or the week before that we mentioned we're doing this because rich text is both the block element and the parent element and we're going to talk about that a lot today. So we can understand the differences. But that's why we had to do it this way. And then the save function because we're just grabbing the props attributes content I'm not worrying about the destructing here so I'm just putting in the props. I could do it like this if I want to like extract attributes from props and then spell that properly, and then just make this attributes props if I wanted to that's another way to do it. But we're just using the props object as is here so that's fine. And then setting up block props which needs is needed for the class name and all those things, passing in the rich test rich text content as the type for element because it's in the save. And then again, using object assigned to assign the tag name and the value to the block props so that it gets used in the rich text component. Okay. That's what we did last week. We also added the attributes to the block.json file. So we added the top level attributes item. We created a content attributes and that's what we're passing around and we're using all over the place. It's of a type string and it reads the HTML source of the selector the select here should be P not text area so if yours is text area please change that to a P. That's a bug in my code. Because if you remember the rich text component that we're using is a paragraph tag we've set it up to be a paragraph tag. So we need to set the content to read it from that paragraph tag so if yours does say text area which I think yours might do because you installed that plugin please change that to a P. So it reads it from that element. Now what's interesting about that is that if you didn't change that it would still work, because there is only one root element it doesn't need to find anything else it'll just find that element and work but later on when we make changes it's going to become important and explain that when we get there. And then finally we have the default value so when we add the block to the page. It presents that default value the first time and then when we change it updates it. I'm not going to dive into the asset file and the styling because that we covered a couple of sessions ago that hasn't changed much. The two main changes with the block json and the main block.js file. I'm going to look at this in our WordPress instance which if I can find my browser there it is, and I go to a page. Let's create a new one for today. And let's say hi JavaScript. And let me just make this a little bit narrower so I can see things a bit better there we go. And if I add this block now there's my JavaScript block. So this is a paragraph tag if we inspect this element. In the editor we'll see there it is it's a paragraph tag so that whole block is is the paragraph tag and the paragraph tag is the block there's nothing else to it. It has the HTML content, which we are able to change. And when that updates and we preview it in a new tab. It changes on the front end but it has different styling because that's the things we applied in the different styles. And that's where we're at today. Any questions on all of that. If you were in the previous sessions you will have been seeing all of that if you weren't some of it might be confusing. So I just want to check if there are any questions about anything I've just shown you. Otherwise we're going to start coding and start adding some things to this. Anyone else doesn't have a quick question I do have one Jonathan. Something that I've come across quite a bit working with other developers and their blocks is the behavior of whatever block they create if they are multiple of those in a single post. I was making it this way if I was at another one changes text out another one and change that text with that behave differently. Let's find out. Let's find out so we can add three of these. And then let's say let's change that one. And let's change this one. So it looks like they've all stayed correct hello JavaScript hello block JavaScript block let's see if it's saved and done correctly on the front end. Hello block JavaScript block. Yes, it looks like it has worked. And I'm pretty sure that's because we specified this correctly with the attributes. So we specified the attributes on this block specifically, and we specified it's a correct selector and the correct source. The minute you instantiate a new instance of that block it's it's attributes get passed. And I'm guessing this this is not fact I assume this is how it works, but it's attributes gets passed to its edit function it's a function every instance, because we set it up the way we have. They all stay as individuals. They're all the individual thing yes. I've never seen because I'll be honest I haven't written many blocks myself my block experiences when I was working with serious simple podcasting. And then another client that I worked for through codeable so I've any worked on two projects where I built blocks. So I've never seen blocks that sort of affect each other like that. I would love to see that in the real world and then debug it and fix it. If anybody has if anybody has seen that it was seen a block that does that in the world like it's an open source block in the WordPress repository they've come across it Leo if you've come across one. I would love to see that and be able to debug that and figure out why. But I've personally never seen it so so it's never been. If you create a reusable reusable reusable blocks do that but not that these blocks that we've created here. Okay. Perfect thanks for that very well chosen. Hopefully that's what I'm supposed to be doing. So let's let's remove these additional blocks I'm so glad that worked I had no idea if it would. Let's remove these these blocks. It should have worked I should I should have trusted myself but you never know you know you know it goes live demo you're there with the client but you're ready to demo to the client and everything breaks. So we've got our block. And now we want to start adding some controls to it so before talk about adding controls let's just review what control elements we have when we talk about blocks. To do that I'm going to switch over to the tutorial page of the of the blocks how to that we've been more or less following in the series. It's talking about the block controls toolbar and sidebar I'm going to just pop this in the chat cookies I don't think I've included this in my in my slides but I will make sure I updated them. I did see that question Michelle I'll get to that in a second. So there are two elements within the block interface that allows us to add controls to our blocks. The first one is the block toolbar the block toolbar appears above the block. Now depending on how you have your block editor configured, it either appears directly above the block in the interface, or you can in this using the options, the options option of the editor you can switch it to. I think it's spotlight mode. I actually remember where it is. Oh, it's this top toolbar there we go. If you click on top toolbar you see it moves the toolbar to the top of the window and it's fixed at the top of the editor there. So every time I changed a different block now let me create let me add a new block here let's create a cover block for example. If I'm working in that cover block then the tools in the toolbar at the top you are belonging to the cover block. If I switch back to my block then the tools change to my block. So some instances of WordPress have the toolbar set up that way with the top toolbar enabled some of them by default it's disabled. And they're pros and cons to both it's up to you what I don't like about having it disabled is when I click on this block for example, the toolbar appears and I can't see my block above it. But what I do like about it is the toolbars right there so it's up to personal preference. But that's the first thing we can work with is the toolbar. The other one is the setting sidebar so whenever you've got a block open if you click on the options in the toolbar. The show or hide the more settings and showing in the hiding of the more settings opens up the sidebar. It's the block tab over here and then it adds additional features and functionality if that's coded in the block. Now you'll notice that the toolbar has very specific icons in the way they look and feel to it. And the sidebar has sort of different icons in a different look and feel the toolbar ones are typically sort of just icons. And then when you click on them they'll open up a bit of a menu and you'll be able to do certain things. The sidebar options are more sort of bigger controls that you can do more things with. So here there's a slider and I've got a value that I can set. Or I can set topography settings or I can change this to do a custom size, or I can do all kinds of it gives you more that you can do and more control. So it's generally recommended that when you set things up that you add items to your toolbar that are sort of short quick result actions like changing the text to bold for example or changing it to italic I one click and that happens. And then things that you're going to set in the in the sidebar would be more sort of advanced functionality that you need more controls. So that's the difference and we're not talking about the toolbar talking about this over here when I talk about the sidebar and talking about this over here. So let's quickly check in on Michelle's question. I'm trying to work with micro formats I figured out how to add classes to individual blocks groups or other items to make it do what I want. Do you think that I can make a block that has the classes on things that I want to insert in a post. That's a good question Michelle and I'm not sure I understand the question fully. And I think if we dive into it today it might take up a little bit of time so what I would like to. What I would like to ask you to do is if you could ask that question in the comments in the meetup group. Okay, yeah, if you could ask it there and then we could maybe dive into it a bit there and maybe even it's another workshop we can do one day, because I'm not quite I need to see it all. So I'm glad you actually asked this question because there's something else that I'm wanting to do this year and now is a great time to talk about it so why not. Michelle actually want to do developer am a live streams. So the goal is, you come with this kind of question. I want to do x y and z how do I do it you send it to me either via email or through a form or through a meetup or whatever, and then I'm going to sit and try and figure it out. Ideally you send me some code that you've worked with already because I'm not going to do this from scratch for you, because that's just cheating. You send me like what you've got working currently and you just need a sort of a push in the right direction and I'm going to. So that's one of the goals for the new year, but please do share that question in the meetup comments. And then we will see if we can create a bit of a discussion around that like maybe if you've got some screenshots of what you're doing and how you're putting things together, and then I can see if I can offer some guidance is that okay. Yes, that's perfect. Thank you. Awesome. No problem. Okay. Let's remove the cover block. Let's disable these things over here. And let us go back to my code. Right. So we were talking about toolbars and we're talking about sidebars. So in the tool if you go to the documentation page and I'm going to scroll there now so you don't have to go if you don't want to if you scroll down to the block toolbar. In the second paragraph under the image of the toolbar. It says if the return type of your blocks edit function includes a block controls element. Then these controls will be shown in the selected blocks toolbar. So the first thing that we need to do is we need to add a block controls element. Okay. So let's do some research on block controls and I'm pretty sure I've got that link in the slides. No, I don't. So I think it's actually because it's linked through from here somewhere. I scroll down a little bit. So I will say this, this is one thing. Yeah, it's not in you. This is one thing that I struggled with a lot when I started developing because this documentation page doesn't have any further documentation about how block controls work. So if you click if you search for block controls as a toolbar item a toolbar button and then there's the WordPress editor. And then there's the WordPress block editor and you're like well which one is which if you have a look at the code on that page. You'll see if we have a look at the plain code you'll see that they are creating the block controls variable from the block editor package, just as we did the rich text from the block editor so that means that block controls is available in the block editor which means if we go to the block editor reference guide, we should see something about block controls. So under reference guides if I go to package reference. And this is one of those things where it's a good idea to start getting used to how to find this information in the in the in the handbook. And if I go to the WordPress block editor package. Here is the block editor package. It tells me how to install it which we don't need to do because we're using the plain JavaScript method. And if we scroll down a bit further, we will see that it starts talking about all the different API things that are available in the block editor package. And if we scroll down a little bit further, we'll see eventually we'll find this block controls, and then it has this very useful piece of documentation that says undocumented declaration. Okay. So as a developer when I first started reading about this I went, that is extremely unhelpful. One of the reasons why we're here today because I want to show you what happens when you implement block controls. So what we do know is that block controls comes from the block editor package so we at least know in our code how we can create an instance of the block controls components. So if we scroll up here to where we've got rich text for example, we can copy out that code and we can just use the same code and we can say instead of rich text we want. block controls and I can't spell apparently. Lock controls, and we can call the block controls API method from the block editor package, which will pass that to the block controls variable and then use it in our code. Now because we did something similar with rich text. So with rich text what do we do we created an element. We passed in the rich text component. We gave it some properties, we can now do the same thing with block controls. So let's take another step back let's go read the documentation again as the documentation said, and I'm specifically not looking at the code yet because I want us to try and think about this theoretically before we look at the code. It says, if the return value of your blocks edit function includes a block controls element. So that means somewhere in this return, we need to add block controls. So that's what that documentation is telling me. So somewhere here I've got to add block controls to this return so that it's part of that return. I've already got the rich text element. I've already got its properties. So how would I go about doing this. Okay. So now we're going to take a little bit of a journey into react lab. Okay. So I want you to follow me down to this link here, which I'm going to open up. So let's talk about rendering an element in the DOM now this if you've never seen it before, we're going to we're going to just briefly cover this, but it says, let's say there's a div somewhere in your HTML file. We call this a root DOM node, because everything inside it will be managed by react DOM applications built with just react usually have a single root DOM node. So what does that mean it means it needs a single parent element effectively. It's a single HTML DOM element if you will, that will contain everything else. Let's go back to the code and let's see do we currently have a single element. Yes we do. We have a rich text element. That's our single element that's that's the paragraph if you remember from the code. Can we add the block controls to the rich text. No we can't. So what that means is we need to define a new root element and then add rich text and the block controls to the new root element. So that's going to be our first step. Okay, so I'm going to leave this code here. And I'm going to show you what this would look like. So we start with the usual return. So that's creating the element. Okay, now we want to create a brand new root element so something that's going to contain all of our block code. And the most common element that usually contains a bunch of children elements is the div. We've all seen it we've all used it multiple times. If you come from the days of tables you remember the days you learned that you could do the same with those as you could with tables and you switch to using divs, you stop using tables. But divs are used as containers on the web. I think we will all agree to that. So a div makes a perfect element to be our root wrapper element and if we look at that react. Example they're using a div element as well which is perfect. So we start by creating that root div element and if you remember from the very first session. When we created just that paragraph element we just pass in the HTML tag name if you the development. Okay, so that's our first parameter, the div. Now we need to think back to when we first saw create elements and I'm going to go to that documentation now so that we can remind ourselves and fortunately that's actually in the block editor so let's open that up as well. Package reference. Block editor. I thought I had it open looks like I've closed it. Or maybe I have got it open and my browser is now I haven't got it. So let's find it quickly. Okay, let's open this in user and let's find create element. It's not on this one. No, it's not a block editor. Sorry. Go back to my code here. Oh, sorry, it's on element create element. I do apologize. Let's do it this way. Let's just search for create element will be quicker that way. Okay. Where is it? Where is it? Where is it? Blocks with press element. There it is with press element. Remember very early on we learned about this. Create element function. And if we go down and have a look at that API, where is create element. There it is. And the parameters, there were three parameters. There was the type, which is either a string. In our case, the div or a component function, for example, the rich text, which we've used before. The second one was the elements properties. In other words, we're passing in things like the value of the element or the unchange event of the element. And the third thing was the elements children. If you remember way back when we first started this, and I'm going to go to the very first bit of block code that we did, which is the very basic block way back when we started with this. You will remember this code. We passed in the paragraph string, which was the type. The second parameter was that empty object of properties because you didn't have any properties. And then the children was just that text, and that was the children of the paragraph. And then you remember when we made it a rich text, we had to change it from children to the value because rich text doesn't want children at once value. A div can work with children. So now we can go back to thinking about the divs properties and the divs children. So with that in mind, let's go back to the code and let's think about how this works. Okay, well, let's not give it any properties for now. Let's leave the properties out of the picture, but let's start talking about children. And let's go back to the documentation. And in the documentation, you'll see there's these three dots. And it says WP element descendant elements multiple, meaning you can pass multiple children elements to your root element that you've created. So how does that work. Well, that means you can do this to copy that out. Now I'm going to copy this out. You can do that. You can also do that. I'm going to make this super, super simple. I'm going to finish coding this and then I'll walk you through what I'm talking about you. Okay. So here I'm saying create a new element of type div. No properties yet. Then give it some children. The first child is a new element using block controls as the content type, whereas the component type with no with no properties for now. And then the next element is the rich text. So that's basically going to add block controls to my development and add the rich text to my, to my, to my element. And I can add more and more and more as I need to. So if, if this, if this block gets more complicated and I want to add a header element above the rich text, I would then add that here. Add a new elements with a header and then, and I can just keep adding multiple elements as I go along. Okay. So any questions don't don't run this code yet because it's going to break. But any questions on this understanding of how we can add multiple elements to one single root element to our return. While I grab a super question. Another quick question for me while you're sipping your coffee Jonathan, since you can take other child elements for example. Is it possible for those child elements to have child elements. Absolutely. So you can have elements within elements, and you can have multiple elements of the root element. You can have, you can have loads of other and in a second, we're going to do that. So, so just hang on Leo. In a second, I'm going to show you how that works. I've got that coming. Okay, cool. But that's a very good question. And in a minute, I'm going to show you how that looks. Okay. So now we, we kind of got the point we can, we can create our parent return for the edit function. We can create our main elements in this case is to do with some properties. And then the children can be the block controls and the rich text. Okay. But now remember when we first implemented block props, so let's go back to that code. And this is why I'm so glad that I documented all of these steps in this repository. When we added style sheets. If you remember, we passed the block props into the properties parameter of the parent element. And the only reason we did the object assigning is because we were passing in in the second step or the third step is because we were using the rich text as the parent element and the rich text couldn't accept children. So what this means is by not having block props as the, as the parent elements properties, we're going to lose out on all that class name functionality. And we're going to lose out on all that cool stuff. So the first step there is to take block props and pass it back here. Remember we spoke last week about block props only being related to the root element, but the properties belonging to the block itself. Block props should always be passed as the properties for the root element. We've changed the root element from from the rich text to the div. So we have to change the properties of that div back to being block props. Okay. I'm going to read Linda I've seen your questions I'll get to those in a second I try to finish up over here. But now that we've taken block props out of the equation now we need to think about well, how do we pass in tag name and on change and value. And still we want those to stay with rich text, because we want rich text to be able to be updated. So now we can take away this object assignment stuff, and we can just pass in the tag name, the unchanged event and the value just to rich text, because rich text is the only element inside of this block that we need to change that we need things to move around. Okay. Let me have a look at the discussions with you. So understanding that rich text doesn't play well with children doesn't matter which position the rich text isn't working because rich text is second. That's a great question. And once we've got this working let's move it around and see. I don't think it matters. But once we so once I get to the point where we've got the toolbar item in the block and we're seeing it I'm going to move it around we're going to see what happens okay so hang with me there. So now we've got block controls as a child of div, and we've got rich text as a child of div. But now we need to add that toolbar, that little toolbar drop down so let's go back over here. I want to be able to change the alignments of my code. And if you have a look at this code here there's an alignment they call it an alignment toolbar. It's also known as an alignment control. Okay. And alignment control is also I seem to remember available in block editor so let's find that there it is so you'll see there's alignment control and alignment toolbar. But if you have a look at the related documentation they both point to alignment control it's the same thing it's just a different name for the same thing. So let's open up that. And this is where I love the block editor. The alignment control renders a drop down menu that displays alignment options for the selected block so whenever I want to do alignments on my blocks. I just use alignment control and all the code is written for me. So I want to implement alignment today so this is what I can use I don't have to go and write this control myself, I can just use the predefined controls that already exist. So how do I do alignment control well as we as we said earlier, alignment control block belongs to the block editor package. So in the same way that we created an instance of block controls from block editor, we can do the same for alignment control so let's do that. So we've got alignment control at the top there. And that comes from the block editor package so that we're doing this for calling that that function, which then sets it up in the variable. And now here's where it comes in alignment control needs to be inside of block controls can't be outside needs to be part of that toolbar. So it needs to be a child of block controls. So here we go on this element line we go comma, and we create a new element. And we pass in alignment control is the type. And again we can pass in an empty object. So there we've got a nested element so we've got block controls as a child of div. And alignment is a control of block controls, and then getting back to rich text that's a child of the parent. So if you think about it in your head, effectively what you let's let's actually let me open up a HTML page so we can kind of think about it in terms of because that's how I like to visualize things in terms of HTML. Let me just create a new HTML file. So we're basically creating is this we're creating the parent does. We're creating another control which will be the block control I'm just pseudocoding this. Then inside of that we're creating the failed on me. Dove maybe here. We're creating the alignment control of, for example, but I don't know if it is a div, but you get the idea. And then after block controls, then we're doing the rich text. So that's what that looks like in terms of if you think about it in terms of HTML structure. Does that does that make sense is what you're seeing on screen and what you're visualizing it does that make sense. Okay, let's see what this code does. So all we've done so far we've created the parent element, given it a time, move the block props to that first object, created the first child element, and said it's going to be block controls type with no options for now. The first child is a new element of alignment control again with no options. And then getting back to over here. This element is a child of the div, which is our rich text element. It has the original tag name, the original unchanged the original attributes that's all the same. We've just separated things out. We've got this other return code here which I need to delete so let's do that. And this is showing me an error. Why that is probably because I have something wrong somewhere. I'm using a closing bracket. That's why there we go. Okay, so always make sure your brackets are closed folks before you run your code. Okay, so let's switch back to the editor and see what this does. So if I remove by current block, a hard reload which will mention you remember we mentioned last time I always do this when I'm developing with blocks so that I get the latest JavaScript. And that's not what I want to move that one. I'm going to save this draft to another hard reload so we get it all. Okay, and then let's add this. Okay, so there we go. So you'll notice that things are slightly different. There's a little bit of extra space around this block. And the reason for that if we inspect this code. It's because we now have, and hopefully you all can see this, you can't actually make this a little bigger. We now have the div, which is the parent root element, which now the div contains the class the data type the title all of those things that come from block props. And then the rich text which is specified as a paragraph tag that only contains the stuff related to the rich text in this case the content. If we make changes here. That's still changes. We still don't see any errors. Yeah, that's all good. This it all still works. Okay, that doesn't look like it's worked 100%. You see, okay, that one's slightly smaller. Let's have a look at what this looks like. So here we have the div again. No, this is not this. Oh, this is because the save hasn't been updated yet. So I haven't saved the save to use the new structure, which is why that's looking the way it does. So let's fix that. So we go back to the code. And now we're going to need to make the same changes here now what we don't need to do is worry about the block controls and alignment controls what we do need to do is make the roots change. So basically it will be changing this to be the div, switching this so that block props is passed to the div the root element. And then creating the child of root of the div, sorry, using rich text and removing all this object assignment because we don't need that anymore. There we go. So now we're doing the same thing we're saying it's the root div passing block pops to the root div. The child is the rich text content we don't need the block controls because this is on the front end, but we're still passing in content the tag name of P and attributes content. So let's check that. We remove that and it's hard reload this. And now we're getting a validation error because what was saved previously and what's going to be saved now is different which we expect because we've made a change to the code. So let's attempt the recovery. And then let's remove it again. I'm going to clear those. Add it in there we go. And then let's preview this. And there we see the changes on the front end if we inspect this. There we see the new div and then we see the paragraph. Okay. I'm going to pause there if there are any questions that anybody wants to understand about what we're doing there. But that's basically setting it up so that we can start using these things. Change so that you just gave us by instruction be part of the get. Yes. Perfect. Thank you. Cool. Okay. So we've updated the return so that now we have a new parent element the div. We've passed the block props to the to the properties object of that div. We've created a first child element which is the block block controls with no with no options. And we've applied the alignment control to block controls again with no options. Then we've specified a second child element of the dip with the rich text using the same paragraph on change and attributes. We know this works we know what this looks like but what is changed in terms of the block itself in terms of the block controls. Well, we now have the alignment in the toolbar. And if you click on it the little alignment pops up and comes back. So you can test if this is actually the change that you've made or not by going back here and removing, for example this alignment control part. So let's see what that does. We just have block controls. And let's see what that does. Okay, the block still looks right. But you'll see there's no alignment. So just by adding that block controls as a child of sorry, adding the alignment control as a child of block controls. It goes and does all this other cool stuff for us and adds the alignment control to our block. So let's refresh. And there's the alignment. Now what happens if I try and change the alignment. That's the next step. So let's see let's see what happens if I say a line text lift. I get an error, which I expect to see. And that error is quite clear on change is not a function to remember that one from the last workshop. We specified the rich text component. We made some changes to it and said, Hey, what do I do with these changes? I don't know what to do with them. So now we need to specify the on change event for the alignment. That needs to get past somewhere, which we know needs to go to an attribute. And then it needs to be saved and then used somewhere. So those are going to be the next steps. So let's start by setting up on change. So if you have a look back at the code we were working on previously, before we started making these changes today, going to pop into that here. We will remember that we passed the unchanged into the properties of the rich text object. Yes, we merged them with block props. But that was because rich text was the parent, but we passed it in with a tag name and the value. So theoretically we should be able to do the same with our alignment control and that is the case. So in the properties for alignment control, here we can say let's specify an on change handler. And we can do it in exactly the same way as we've done on change content. We just do on change colon space and then we define a function. And so in this case, I'm just going to call it on change alignment. That's all I'm going to do there. Now I need to specify this function. So we can just copy the on change content there. And make it on change alignment, it'll receive a new content, a new alignment. So let's rather make it new alignment. This doesn't have to be alignment. It's just going to be a value. We're calling it alignment. So it makes sense to ourselves. You could call it new Bob if you wanted it doesn't matter. But I like to call it something that makes sense. So let's call it new alignment. And then we need to set attributes. So the attribute is not content. We're going to need to create an attribute called alignment. So let's just make this alignment now. And we'll pass it in the new alignment. Okay. So that's the function set up. But now we need that attribute to be available. So we created those in our block to Jason file. So let's go and do that. So in block to Jason. Under the top level attributes, we can create a new one. So we can call it alignment. And then just as content has some, some properties, we can say alignment has some properties. Sorry. Forgot to come over there. And we'll just make it a string type for now. And let's give it a default value. And in this case, our default value is going to be none. Now the reason for this is when you read through the documentation for the alignment control, which I think I might still have open here. Yeah, there it is. You'll see the available options are left center or right. We, we don't want any of those to be the default. So we'll just make it the English word none. So that kind of matches with that option. But once it gets changed as one of those three options will come through and then we'll get stored. So let's have a look at the code. So we've defaulted to none. So when the on change events of the alignment control fires, it'll pass one of those three to new alignment. New alignment. And it will then use the set attributes function to pass alignment back to new alignment. And our alignment will change. Now that's all well and good, but the alignment is not being used anywhere. Now where would we want to align? What would we want to align? We would want to align the rich text content because that's the main part of, we don't want to align the rich text inside the div. We want to align the content. And the cool thing with the rich text is we can apply a style attributes. So here we go style. No, not style sheet. Sorry. And we can specify and I might need to check my notes here because I've forgotten this. One sec. It's actually, it's actually in this code in the repo right now. So you can actually just steal it from there. Where is it? Yeah. Text align attributes aligned. Okay. So we're going to code this now and then like explain what this is doing in a second. So in the style, we can just pass in text align attributes alignment. Here we go. And that'll do it for the editor preview, but we now need to do the same for the same. So again, we copy out that style there. In the rich text under the tag name, we pop in the style there. And because we're not using the attributes destructuring yet, the props attributes, we can just update this. So it's props attributes alignment. So let's walk through this code. So when the alignment control changes, so when the user clicks on the alignment control, unchange handler will fire and it'll call the unchange alignment function. That function will take the new value either left center or right and update the alignment attributes with that value. That attribute will get passed to the save function down here in the properties. And it'll change the styles text alignment to that new value. It'll also do it in the styles text alignment for the rich text. Let's see if this works. So we'll start by removing. I need to move some video screens around again. So we'll start by removing that. Then we'll do a hard reload. We're getting some validation again because we've made code changes, so that's fine. Let's just do that and remove it and refresh again. I'm going to just save this draft so it doesn't have any changes. Okay, there we go. So let's add the block. First step. Let's see what happens when we make changes. Center. Because it's changed the alignment to center. Right. Because it's changed the alignment to right. Left because it's changed the alignment to there. So we're happy that that works. So let's make it center, for example. And then let's preview this. Preview the new tab and there it is centered. Okay. So now what's great about this with a few lines of code, we were using this implementation of these components and making things work. And the cool thing is there are toolbar elements and control elements and all kinds of other fun things that will make this work all over the place. Okay. Now somebody had a question while we're here. Somebody had a question about things moving around in children that which I think is a good time now to dive into. But before we go on, does anybody have any questions about what we've done so far about setting up the alignment control, setting up the attributes, updating the style of the elements and passing that to you. Any questions around all of that? I think it was pretty clear and very well done, Jonathan. The question that Linda had had around child elements was if the rich text editor is a child element, but does that mean that he cannot have its own child elements? So let's let's do that. Let's see what happens. So what I'm going to do here is in rich text, I'm going to create a child element. I'm going to say element. And let's make it just a plain paragraph. And let's not give it any properties. Actually, let's make it a span because a span would make more sense inside of a paragraph. Semantically. Andrea, I'm sure I can do that. Actually, the easier way to do, let me finish this and then I'll paste to the code. So I'm going to do that. And then I'm going to give it a child element of just some text. So span text. So that's a child element of rich text. OK. Let's see what that does. And then Adrian, I'll paste the code for you. Let's remove. Save it and refresh. And let's add the block. OK, those errors we expected. Let's add the block. And it throws an error. So let's see what that error says. So we can understand what the error means. Children is not a function of rich text. So rich text is a specific component that cannot accept children. If you remember, we experienced that when we changed from using the paragraph tags to the rich text. We had to change things around. We had to do that object assigning. Rich text is a specific component that cannot accept children. Other components can. Top level plain HTML elements like divs and paragraphs can. But rich text specifically can't. OK. Cool. Let's go back to this. And let's change this art. Adrian, I think what I might have to do is pop this into a gist for you because I don't think that the chat window will allow me to paste the whole code. So I'm going to quickly create this and then I'll share the link with you. I'm going to pop that in there and create a public one. And then I'll share that with you. And let me know. OK. React create element type is in Berlin. Make sure you're using this this function for creating an element. Remember use those to make sure that's there. You're welcome to create it just for me and send it my way and we can try it out if you want to give that a shot. I'll see what I can figure out. I'm sure it's a small error, but I want it. It could be like a missing comma or a missing bracket or somewhere. So maybe have a look through that. Back to the first question. Does it matter where the rich? Yes, let's see. Let's have a look. Let's have a look. I want to see that myself. So let's take rich text, for example. And let's pop it above block controls. And see what happens. Let's do that. And that let's see what happens there. So the answer to that question about can't does it matter where a place is kind of yes and kind of no. And I'll show you what I mean in a second. Let's reload all of this. See now there I'm getting some errors already. That could be because it says attributes is not defined. That could be something related to the attributes. Oh, it's because I think I've done it in the wrong place. See here. Getting lost in my own code because it's so big. I'm just going to zoom out a little bit. That's fine. I think I've gone back too far. That's why. Yeah. I was messing with the save function. That's why. Okay. So we want that to be above block controls. That's what we want there. That's what we want. Okay. So this isn't the edit function. So I've got the dove. I've got the block props. Then I've got rich text first. Then I've got the block controls. So let's see what happens. That's actually what I wanted to test. Okay. Let's remove this just in case we get the latest code. Let's do a hard reload. It seems to be fine. It seems to be quite happy to do that. Now I do know that this is possibly specific to block controls because when block controls and the alignment controls are used, it knows to add it to the toolbar, but it looks like it doesn't matter where you add it in the, in the view. However, let's, let's talk about this for a second. Let's say we wanted our block to contain, let's say two rich text elements for whatever reason, then it would matter which one goes first, because then it would render them differently in the view. But when you're using block controls and your block elements, where you put block controls, doesn't matter because it'll always render it in the toolbar or in the sidebar. Does that make sense? But when you're putting your block together, if you're working with the controls or the elements inside the block visually to the user, then it probably does make a difference because you want one to load before the other, before the other, so that it looks a certain way. I hope that makes sense. Okay. Any other questions on all of that? Adrienne, have you had any, any luck with your, your things yet? Not yet. Okay. Do you want to, do you want to create a gist of what your code, no, let's, like, I'm, I'm keen to do this. If you want to create a code, a gist of what your code looks like right now, and we can paste it in my window and we can see what we can find. Would you be okay with it? Yeah. Okay, cool. Sure. I'm sure it's something really silly. Well, that's, that's the thing about writing code is the amount of times that I've hit my head against the wall for two hours because of a missing comma is not even laughable. So it's good to pick up these things and see what these things are. So please do if you, if you can send it to me. I pasted it in as a comment. Does that work? Yeah. I think with the zoom chat, the commenting system doesn't work so great. Oh, no, I pasted it in as a comment on the, on the gist. Oh, I see. I'm with you. I'm with you. I'm with you. I'm with you. Okay. Let's refresh. Okay. Here we go. Okay. Let's do this. I'm so keen for this. Live debugging folks. How the sausage is made. Absolutely. Okay. Let's have a look through the code. So that's all fine. That looks good. That looks fine. I think this is all fine. It could be a, it could be a refreshing problem. That all looks fine. That's using attributes. That's all fine. Let's see. Oh, here it is. Here it is. Here it is. So remember. In the save function, we're just passing in props. We're not doing the destructuring of props. So when you reference the alignment here, it needs to be props attributes. In the save function. In the save function. Yes. This is actually a good point. We might want to update this code so that it's more uniform. But try that and see if that fixes things. I'm going to test it on my side. Okay. I'm getting, okay. I'm seeing some, some errors. No, that's not related to your stuff. That's related to some extension that I have. So it looks fine. So let's clear these out. And okay. Okay. Okay. We're seeing an area. Let's see what this error says. This is cool. I love this. Live debugging. Let's see. Okay. Okay. So let's have a look at edit. So edit function. Attributes that's fine. Block props on change on change alignment. That looks fine. The original one had been something about in the edit function. Something about an issue with the create. Okay. Okay. So what I'm going to do now is I'm going to. Grab. My code. And we're going to compare. I'm going to see what's going on. Yes. And let me find this. Um, can I remember how these things work? Now this might get tricky for me because I don't use the edit function. I'm going to use the edit function. So I'm going to use the edit function. Now this might get tricky for me because I don't use code a lot. So if anybody knows, maybe you know how to view these things side by side. It'll help us debug this. You can, I think if you right click when you. Yeah, you should be able to do them side by side. If that's what you're looking to do. Yeah, that's that's what I'm looking for split right. Yes, there we go. That's what I want. Okay, so there's yours. So yours is I'm going to. So mine is on the right. Yours is on the left. Okay, so looking through. That all looks fine. Function set attributes use props function change content that looks good. Content alignment that looks fine. Okay, let's have a look at the return. Crop control. Alignment controls. I'm in control. That's what it is. Thank you. There you go. That's fine. And that's, and that's a good, this is a good example though of one of the sort of downsides of working in JavaScript is sometimes and. I could be wrong here. This might not be JavaScript specific that might be a visual code thing. If I was working in my PHP store environment PHP storm would have possibly picked up that I specified alignment. Control. At the top or at least alignment control there and then not at the bottom or whatever the case was or it might have auto corrected correctly or whatever. So it's alignment control there and then alignment control there. So that it works. So that that might have been picked up in PHP storm. Because I don't have my visual code studio set up to do all those things. I would have missed it. But this is a cool way of seeing these kind of things and figuring stuff. So awesome. Thank you for showing that with us. No problem. Okay. So let us refresh this. You have no idea how nervous I was there that I wouldn't find it. And there we go. It's all working. Excellent. Okay. Cool. So for fun, what I'd like you to do now, if you're coding along with me, as I want you to see what happens if you just make one small change from using, let me close out some of these windows from using the block controls to using something called the inspector controls underneath block controls. I want you to create an instance of inspector controls specter controls. And that comes from the block editor package. And I'll show you what I'm talking about in a second. And then all I want you to do in your edit and your save function is update wherever you've got block controls and change that to inspector controls. It should only be in one place in your edit function. The alignment control stays the same. The unchanged stays the same. All of that stays the same. Just change block controls to inspector controls and make sure you are creating an instance of inspector controls here. And let me show you what that does. So if I remove this and I refresh. You will see that when I click on the block now the alignment is missing over here, but it's moved to the sidebar. So just by making that one small change, I can switch which toolbar, which sidebar my controls are sitting. So block controls manages the block toolbar. Inspector controls manages the block sidebar. It is a bit confusing because they call it the toolbar and the sidebar, but the component that manages the toolbars block controls and the component that manages the sidebars inspector controls. It would be cool if it was toolbar controls and sidebar controls. That would make life a lot easier, but that's a good thing to remember. You'll notice here if I do the alignment settings, it all still works. It's still doing the alignments for me. And if I save it on the front end, it's still going to do that. It doesn't look great because the alignment control is specifically designed to be used in the toolbar, but it shows you how you can quickly move things around. So if you're building your block and you realize, well, actually this thing would be better in the sidebar. You can just switch the block controls to the inspector controls and it'll all just work. Okay. Now there's a few other things I want to show you today before we wrap this up, but are there any questions about what we've covered here so far? Otherwise, I just want to show you one or two other small things that we need to do, which will make things just a little bit nicer and neater. I have a slightly adjacent question that I had when you were talking about Visual Studio and PHP Storm. Is there any, I believe you're using Visual Studio correct Jonathan? For these sessions, yes. Day to day I use PHP Storm, but for these sessions I use VS Code. Okay. So I'm assuming you don't have any special packages. So if you have any recommendations, you're welcome to share them now, but unfortunately I don't have any because I use PHP Storm full time. I actually do have a few Visual Studio packages that I would recommend for doing blocks and themes. So I'll post that in the Meetup chat if that's fine. That would be perfect. Yes. Because I don't use VS Code Studio, if anybody does have packages that they want to share, that would be lovely. So please do. And then maybe Leo, you and I can do a session later where you show me how to set up my VS Code so that it can do all those cool things. Cool. And this is, can you go back to the browser window? It shows the advanced button in the sidebar. Is there anything there? Are you talking about this? No. Yes. Yes. Oh, yes, the advanced. So this is a default panel in the sidebar. At the moment it just has the additional CSS classes option. So basically what this does is if I put in a CSS class here it will apply it to the block. You can use that to style the block with custom styling. What I do want to mention and when we get into block supports and the custom, so when we do the custom property, custom attributes, which will not be next week, but probably the week after, we're going to add that attribute to the sidebar because it's going to be like an image upload thing that we want to do. And I'm going to have to show you when you, you'll notice with the alignment here, I have no idea what this is. I have no heading like I have here with advanced. I have no labels or anything. I'm not nicely centered on the sidebar. So there's some additional, some additional code you need to write to get that all to work. So it looks nice and neat in the sidebar. So we'll do that in a future session when we do that, that custom, what we'll basically build is we'll build a custom element. It'll just be like a custom button, HMR button. We'll actually build our own custom component on that day. And then just like we pulled in the alignment control components and use it in the block code, custom component and our custom component. And I'm hoping we can cover that in one session because building custom components is a little bit trickier because you have to build everything yourself. That's why I want to try and keep it simple. I just want to make it a button that you just click and it opens up the media library and pulls an image in. Hopefully. I don't know yet if it's going to work in one session. We might have to split it over too. Okay. Cool. So a couple of things I need to mention before we wrap up today. When you are defining and I'm going to open up this and I'm going to open up the documentation for this. So if you aren't aware, all of these steps that we've been working through, I've been documenting in this learned JavaScript repo. It's the same repository where you downloaded the plugin file from. I'm just going to paste it there quickly. Each step in the process. I have also documented with a read me file. So you can read through all the steps. We covered step one and two in the first session. We covered step three in both the second and the third session. And we're now in step four, which is the block controls. And I'm just going to open that up because right at the bottom here, I've got some things that I need to mention. The first thing is that sort of right to the bottom here. While we're talking about this is why we're talking about toolbars and sidebars in the plain JavaScript example code. A key property is past the properties object for both block controls and inspector controls. So let me show you what I'm talking about there. So in the code here, if we scroll down to block controls. No, not that one. This one playing. Here we go. Block controls. There it is. It has this key being passed in the property. Properties object. And if you find any example code, I don't know where it is now, but there's example code of how to implement inspector controls in plain JavaScript. There's a key property pass as well. The recommended way of doing this is to pass in controls as the key for any block control implementations and settings as the key for any inspector controls. Now the reason you need to do that and I've got this link in one of these. I'm going to find it's the last one on page two. I'm going to open that up quickly. Specifically in react keys help react identify which items have changed or added or removed. So it's a special react thing. And for block controls and inspector controls, you need to implement that. So that's the first thing I want to do. So I'm going to go over to my block code here. I'm going to change this back to block controls. Just because I want it back in the toolbar. So we'll take inspector controls out. And then I'm just going to pass that key in this object here. So the key is controls. I think it was just check that. Yeah, key controls. There it is. There's just copy that out as is. Actually, yeah, that's fine. Okay. That's the one thing. And then the other thing I wanted to show you is this. And if you've never seen what's known as the ternary operator before, this is going to be something possibly new for you today, but we'll try and we'll try and just cover it briefly. If you have a look at this code example I have here, you'll see the unchanged alignment function has a little bit more code than what we've got in the set attributes. It's basically saying alignment equals. So set alignment to, but if the new alignment is undefined, then sets it to none. So I set it to the new alignment. And this is because if you in the, in the component in the alignment control component, if the user selects an alignment and then selects that same alignment to disable the alignment, then it passes back a value of undefined. So we need to cover that value as well. So this code I'm just going to copy out from here. And I'm going to pop it in. I'll show you what that looks like. So instead of just setting it to the new alignment, I'm just going to copy the whole thing. Okay. So we're going to do it this way. So what this, what the structure looks like is it's called a ternary operator. It's basically, this whole section is the condition. So it's the same as doing this. And I'm actually going to write this out so we can understand it. It's exactly the same as saying if new alignment is undefined, then new alignment must be none. Or otherwise new alignment is effectively just itself. So we didn't have to do that else. But basically this whole section here says, if new alignment is undefined, return none, otherwise just return new alignment back to the alignment attribute. So that's what we're doing there. So that's another thing that is good to do. I've got some additional races here. So I'm going to take that out and take that out. And those are two. So whenever you're working with something, whenever you're working with a block component that allows us, allows us, allows the user to enable or disable settings, always be prepared for a possible undefined. And if it's undefined, set it to whatever your default value is in our case, none. Otherwise possibly the new value. Okay. So that's what we've done there. That I think is that. So let's go back to the browser and check that that all works. So we'll remove that out of there. We don't need the auto save. Let's just save the draft and it's refresh this. And there we go. What's going on here? Can I convert undefined? But that's again, I need to figure out what browser extension that is. That's giving me this error. But that's all fine. Whenever I see it, I freak out and I think it's my code. So let's add the block. And there it is. And we can move things around now, which is great. One thing I am noticing, and I don't know why, but when I select these alignments here, I should be seeing that the alignment is actually set. And it's not actually setting it. It should change to that icon or that icon. So I actually need to see why that's happening. Yeah. SWATCH has just asked exactly the same question. So I'm going to quickly run through my, my code here and see what I've done wrong. Oh, it's the value. That's what it is. In the alignment control, we also need to specify the value to the alignment control so that it knows to update the value and make it show the correct value in the control. So in the properties for alignment control, we need to pass the alignment value to that control as a value in the object. Thank you. I don't know what your first name is, but thank you, for pointing that out. I did notice it earlier, but I wanted to get to it. So if we pop that in, then we will see that it should now work. So let's remove. And it's hard reload. And there we go. And now if we do, there we go, you see it's, it's set now to left. And when we set it to right, it changes to right, which is what we want. And you'll see their right has changed. If we disable right, it'll go, it'll, undefined will be passed. It'll be set to none, which is what we need. If we set it to center, it changes to center. If we set it to right, it changes to right. And the reason that works is we could be passed the new line of control and it picked it up and said, okay, fine. This is what I need to set. So that's why that works. The good thing to note or the thing to, the thing to be aware of here is it's very difficult to dive deeply into all of these components, how they work, how the value works, how the on change works. So there's a little bit of digging that you have to do into the documentation. If we go into the documentation for that control that we looked at earlier, it was here somewhere to be find it. This one over here, it talks about, yeah, it talks about setting the value. It talks about setting the on change here. They're doing the on change inside of the alignment. It talks about the current value of the alignment. So you do need to read through the documentation to understand what these things are doing. But hopefully this will give you a good starting point. So now that you understand how alignment control works and you understand what the props are and what the on change are and how it all works. The next time you see another control, you'll know where to start looking for that information. One information you have to pass around to get things to work. Cool. That is basically what I wanted to cover today. Are there any other questions around all of that that anybody has at this point in time? Jonathan, other than our developer docs, like we came across that one section that says these docs will need to be worked on. If we come into cases like that, is there any place we can ask questions that you would recommend? So I'm going to recommend what I did when I started developing with blocks. Find one of the Gutenberg core developers who works it automatic because that means they're sponsored to do this and bug them. I'm not going to mention names because then everybody's going to bug him. But there was a developer who I came into contact with at some point in time. And I saw that developer being very friendly. And then I asked him a question and he gave me an answer. And the next time I asked him a question and he gave me an answer and I just bugged him ever since. So I'm going to also say that, however, feel free to bug me. I'm a developer who works automatic. I'm happy to either find answers for you or point you in the right direction. Most of the folks that I work with in the open source team who works automatic are all very friendly and very willing to help. There is also, yes, please feel free to bug me. The best place to bug me. So if you aren't there already, the best place to bug me is the make WordPress Slack because part of my job is being online in that Slack all day long. And basically I'm going to paste this URL in the chat. Excellent. Thank you, Leo. So the WordPress Slack instance, it's basically the open source instance for putting together a WordPress and building WordPress. But feel free to reach out to me if you get stuck with anything. What I will say though is don't reach out to me to build your features for you. That I'm not going to do. Hopefully you've tried something and you've got something to like we had with Andrea earlier. She got to a point where something wasn't working and she couldn't figure out what that one of the thing is. If she reached out to me, like when she was working on a project, if she reached out to me and said, hey, this is what I'm stuck with. And I said, yeah, I'm stuck with something, it's just not easy learning. Can you help me out? I said, yes, send me the code, a GitHub repo or text pasted or a gist or whatever. And I'll gladly have a look. Or if it's a case of I don't know how to build a certain thing. What documentation do you recommend I read? Or how do I find this or how do I find that? Please feel free to message me in the WordPress Slack. I do try and reply to everybody within 24 hours. either point you in the right direction or point you to someone who knows the answer. This, however, is another reason why I'm doing this developer AMAs next year. So I have a friend in Johannesburg in South Africa who recently reached out to me with a problem he was having with blocks. And my plan next week is to actually look into that problem and see if I can figure out why it's not working for him. He's built everything. Everything is working, but it wasn't working the way he wanted it to work. So he's trying to understand why. So now I'm gonna take the code that he's got and I'm gonna see if I can figure that a small piece out for him. So I'm happy to do those. But please don't use this opportunity to not get me to build your features that I won't do. But yes, that's the best way. If you're not finding answers, reach out to somebody you know, reach out to me. If you join the WordPress Slack, start hanging out. I'm actually gonna open up my Slack instance. I'm gonna make sure I'm on the making WordPress Slack, which I think I am. I think I've got Leo's chat open. So that's perfect. There is a core editor channel which is all about WordPress core editor development. You can sometimes ask questions there and folks will point you in the right direction. If they don't, they'll send you to various places. The WordPress support channel is also a good place. And I will say that there's actually also a team within Automatic that tries to monitor support specifically for developer-related questions. One of the first things that I had to do, let me just find the support. Let me find the... Try to do the debugging with the support forums. So in the support forums, there is a developing with WordPress forum. And you can post questions here about how do I do this and how do I do that? And there are people who will monitor those forum posts as well. So you're welcome to ask questions there. But the best thing to do is try and build a relationship with one of the core Gutenberg developers that you can reach out to. That's what I did. I was lucky I built that relationship and I would reach out to him and I would say, hi, I hope you're well. I'm busy building X, Y, Z and I'm busy doing this and I'm struggling with this piece. And then he would point me to some documentation or point me in a direction and then I would usually be able to figure it out. But those are some options that you can try. Okay, cool. Well, that's my bit for today. Thank you everybody for joining me. I hope you have enjoyed the session. As I mentioned earlier, this is all being logged in that Learn JavaScript Propositary. So if you wanna go through this again later, if you're busy watching the video and you wanna review the code, it is all there. You could download all the different parts as we're building through this to see the previous parts and then build on top of them. All of the code is sitting in different folders. I'm planning on adding it as we do go along. So it'll be something you can always refer to. Yes, documentation can be intimidating. That's one of the reasons I'm doing these sessions. If you have any questions that I think it was Michelle with that question earlier, please hit that hit me up in the meetup channel or via Slack. If you wanna ask me that question I'm also happy to do that. One of the things that we're planning in the training team is a sort of learning forum, a platform where folks can ask these kind of questions. So it's a sort of a stretch goal we have for 2023. So if that kicks off, that'll also be a place where you can ask for help. So yeah, but thank you all for joining me. So let me to see you all again. And as I say, next week, we're gonna be looking at block supports. We're gonna be looking at how that works and lesser changes, but it shouldn't. Thank you again, Leo for co-hosting with me today. Enjoy the rest of your Thursday and the rest of your week and I will see you all when I see you. Have a great day everyone.