 Okay, we are recording, we are live, welcome everybody. It is, as I mentioned, the Thursday, the 24th of November, which in the US and many other countries is Thanksgiving. So for those of you who are joining me today, welcome. If you're still busy getting your WordPress environment ready, please remember to download the plugin. I will copy the plugin link and paste it into the chat for you. And you can just grab that if you haven't already. And then we can go on. So today we're gonna continue developing blocks without React. We're gonna be focusing on attributes and the rich text component today, because those are two things work well together. But before we get going, a few announcements as usual. Again, welcome to everybody, welcome to everybody joining today. I don't have a co-host with me today, unfortunately. So please bear with me while I copy links into the chat as we go through. And please bear with me if I don't see your questions in the chat immediately, but I will keep checking the chat for any questions. As always, we are presenting in focus mode, but please do consider enabling your video if you would like to. So I can see you if you want me to see you. You are as always welcome to ask questions and you're welcome to either post them in the chat or unmute to ask questions as we go through. Okay, then moving on. I'm gonna mention this very briefly, but please do consider taking the WordPress learner survey. If you've been using the tutorials and the lesson plans and the workshops on the Learn WordPress platform, we want to know what folks like, what they don't like, what they want us to do more of, what they want us to do less of. So please do consider taking that survey. One last reminder to get your local install ready. If you haven't already downloaded and install the plugin. And as always, if I'm going too fast, please do let me know. And today I am limited by time, so I might rush a little bit and I apologize for that. I will be posting this to WordPress TV afterwards. And for more WordPress focus content, do visit learn.wordpress.org. Okay, so today, as I said, we're going to be carrying on from the part one workshop that we did where we started building a basic block. We're going to be reviewing that code just very quickly running through what we did there. And then we're going to cover some general developer tools, principles for block development, some things that I find handy when I'm developing blocks. Then we're going to add an attribute to the block. And we're gonna talk about attributes and how they work. And then we're going to implement the rich text components so that we can edit that attribute. And I'll explain why we use the rich text components in this example and why it's a good piece of code to use. And then we're gonna make it possible to edit and save the content of the block using the rich text components and the attribute. Okay, so our objectives for today. Very quickly, we're gonna review the block code. We're gonna look at browser development tools, clearing the browser cache and enabling WordPress debugging, which is something very useful when you're working with WordPress code. Then we're gonna add the string attribute to the block. We're gonna update the attributes and include a default value so that the value passes through. Then I'm gonna show you how the attribute has passed to the block. And while we're there, we're gonna talk about the difference between a block's properties or props and block props, which is a special thing. Then we're going to implement the rich text components so that folks can edit the block. We're going to update the component to use the attribute value. And then we're also going to implement some unchanged functionality so that you can edit the code and it'll save it back to the attribute. And that'll be using the set attributes function and we'll talk about that when we talk about the props. And then we're gonna update the save function to also use the rich text for the content and the rendering and the updated value so that when we edit it in the edit function and in the editor, it changes the attribute value, saves it in the save, and then presents it on the frontend. And then if there's time, which we might not have in this session, if we run out of time, I'll record it separately, we'll be doing some refactoring and some cleanup before we move on to the next step. Okay, hopefully everybody is ready to go. Let's do some coding. So just as a refresher, I have got the plugin installed, it's currently at version 0.0.2. I do have it on my desktop and I just quickly installed it before we started. I'm gonna pop over to my code editor so we can have a look at what the plugin does and just review that code very quickly. So we created in the first session, we created the block.json file, which is the block metadata. So it's all the information about the block. It includes the title and includes the name of the block, the category that belongs to the icon and then maps the files that it needs to map to. So the main editor script file, which is the main block file and then any style sheets that it uses. We also created the asset file, which manages all the dependencies for the block. And I mentioned that if you're using Node.js or NPM to build your block every time using that build step, this file gets regenerated for you every time. If you're not using that, which is what we're doing, you have to manually add your dependencies to this file. We created the main block code, the block.js file and we implemented the blocks element and block editor modules or packages or components that are available in the global WP element. It's this window WP element. So that ships with WordPress. It's available when WordPress loads. It loads it up in JavaScript. It's a JavaScript object that you can always implement. And we then pass those through to this I-F-E-E function. It's an automatically running function. It fires automatically. And we set up the blocks element and block editor variables to be able to pull things from there. We then set up this variable called EL, which is basically just a copy of the create element function so that we can create the elements in our edit and save functions. We use the register block type function to register the block type and we made sure that we gave it the same name parameter as we specified in block JSON over here. And then we specified an edit function, which is the function that fires when you are editing the block and it's what renders to the user in the editor. And all we did there was we returned a simple element of a paragraph type or a P tag. We made sure we got the block props from the use block props hook, which we'll be discussing in a second. And then we just gave it a very simple child element of some text. So the paragraph has a child element and that's just the text. And then in the save function, we effectively did the same thing. We set up the block props again and we've returned a similar element. And the only difference there was we changed the text in the editor one in the front end differently so that we could see what they look like. The other thing we did, if we have a look at the block to JSON, we specified some styling. So we specified a style sheet for that gets loaded in the editor. And we specified a style sheet that gets loaded when it's rendering on the front end. And in the editor style sheet, we have a green background, white text and 20 pixels of padding. And in the front end, we had a red background, white text and 20 pixels of padding. So let's have a look at what that just looks like in the front end very quickly, or at least in both the editor and the front end. So I'm going to go to a post and I'm going to create a new post for today. And I'm going to say, hello, JavaScript, just for fun. And I'm going to add my block and there's my learn JavaScript block. And there it is. It has some plain text. It has the green background and the padding and all those kinds of things. And if I then preview this in a new tab, in other words, rendering on the front end, there is the red with the different text. So that's how it all works. It was very simple. We can't edit it. We can only move it around or remove it from the editor. Okay, so that's where we are now and we're going to continue from here. Now, ideally, we would want the user to be able to edit this information. So currently, if you look at developer tools, and we're going to talk about developer tools in a second, I'm just going to open them up very quickly. This is just a paragraph tag. So a paragraph tag is a static thing. It doesn't allow any editing. So we would like to implement some way of the user being able to edit this in the editor and then some way of saving it. And that's where attributes and the rich text component comes in. Before we go any further, while we're looking at developer tools, let's talk about some developer tools, some tips and tricks around when you're developing with WordPress in general or with blocks, specifically with blocks that you can use to kind of speed up things and see problems as they happen. So the first thing that I want to share with you is specifically the browser developer tools. And I actually went and grabbed a link that talks about where all the different developer tools are in the different browsers. So you're welcome to open this up on your side, but I'm gonna load it up on my screen very quickly. Most of the modern browsers all have a developer tools console and you can access it in various different ways. And if we scroll down here, it talks about, it's either command option C on a Mac or control shift C or I or L on Windows, Linux, whatever or F12 if you're using different browsers. So depending on what browser you use, it's a good idea to figure out where your developer tools are. I am using the Brave browser, which uses the Chromium base, which is what Chrome is built on. So when I am working and I wanna switch on developer tools, I can simply hit F12 on my keyboard and that pops up my developer tools. I have it on the right hand side. Some folks have it at the bottom. The other option is you can click on the options or the settings for the browser and scroll down to more tools and then it's their developer tools and the keyboard shortcut is the, I think it's the option command I or L keyboard shortcut and that opens developer tools. And the three main things that I use in developer tools are the elements pane which shows the, all of the markup of the page. You can right click on any element in the page, inspect it and that'll jump to that element in the elements tab. So there's the header, for example and if we right click on there and go inspect and it'll jump to that paragraph tag and we can see what that paragraph tags code looks like. Then we have the console. This is very useful for when you're developing in JavaScript which is what we're doing and this is where you can see any kinds of errors that might be happening in your JavaScript and you can also log things to the console which we will be doing in a second so that you can inspect objects and variables and that kind of thing. And then finally the sources one just shows you what things are being loaded. I don't use this that much but it's handy to know how this works. And then last but not least I forgot about the network tab. This is another popular one. You can see your Ajax requests and you can see anything that's being fetched any images and those kinds of things. I don't use that so much when I'm developing blocks I'm using mostly the elements tab and the console tab. Okay, so that's developer tools. I do recommend figuring out how to open your DevTools. It's the shorthand for it and how to switch between the elements and all the console. Linda says, are DevTools different than right clicking and hitting inspect? No, when you right click and hit inspect you're effectively opening up DevTools and going straight to the elements tab and viewing that element. So that capability of hitting right click and inspect switches on DevTools for you. So that's another way you can do it. That's the great thing about the DevTools in the browser the easy way is just right click inspect and then it's there and it's available. So that's how you get around that. The tabs on called slightly different things in the different browsers. So it's not something that I can explain to everybody otherwise I have to load Chrome, Internet Explorer, Safari, Firefox and go through them all but it's good for you to, excuse me, get used to your developer tools set up in your browser, understand where things are, how to get there and how it all works. Okay, so that was DevTools. The other thing is about clearing the browser cache. Now the reason that I mentioned DevTools first is because in most browsers, Firefox is included and most Chrome based browsers which these days includes Brave and the new Microsoft Edge browser. If you have your DevTools open in any one of these tabs either console any one of these open the whole thing is open you can then usually on your refresh button which is in the top left of my page here you can right click on it and then there's usually a last option something along the lines of empty cache and hard refresh or hard reload or something like that. You'll see there's no shortcut attached to it because they only make it available when developer tools are switched on. Now what's handy about that when you're working with JavaScript because browsers are clever and they cache all the front end rendering stuff so all the style sheets and the images in the JavaScript sometimes when you're working with JavaScript code and you just refresh your browser you might not see the latest version of the code. So I am always when I'm developing in blocks developing with my developer tools open and then I'm always using the empty cache and hard reload option. So if something is not quite working the way you expected to and I think we've had this in a previous workshop where this happened always use your empty cache and hard reload and that'll reload everything you'll notice when I reload now my block will actually disappear from the editor because I hadn't, I know it's kept it there because I think I might have saved it I don't expect that to disappear but anyway it might have been because I previewed it so it saved it but if you were just adding it and refreshing then it would disappear because it hadn't actually been saved. So it's a good idea to have your hard refresh option available to you know where it is and how to find it it's usually right clicking on the refresh button and then selecting empty cache and hard reload and then finally I want to chat about WordPress debugging we covered this in a previous section almost by accident it's always a good idea in your local WordPress install so I'm gonna switch back to my code editor here and I'm going to go and find my wpconfig.php file it's always a good idea to have these two constants these two PHP constants enabled or switched to true the first one is wp debug which is the WordPress debug so any kind of PHP code it'll basically by default that's offered set to false and what that does is that suppresses any PHP errors it's a good idea to have that on when you're developing on your local environment so that you see any errors and the other one is the script debug option it's a good idea to have that on the reason for that is in the WordPress code base the JavaScript code that is written for most things is written in a clean human readable format and then usually either transpiled or minified or whatever process before it goes to production if you switch script debug on then it loads the developer version of that code so both versions are shipped with WordPress but any of the minified or transpiled one is used but if you enable script debug it'll use the developer version and again any possible errors that you might see or any warnings that you might see will also show in your console which is what we actually saw in a previous session so I do recommend switching those on you go into your wp-config file you scroll down to run about line 82 there's a defined wp debug one that's usually set to false so change that to true and then below that you can do the defined script debug one and set that to true as well also notice that you put the constants in quotes either single or double quotes and then the true or false is just without quotes because that's a Boolean value so it's just the define with the brackets and then the constant that you're defining either wp-debug or script debug and then you set that to true Okay, any questions on all of the debugging things we spoke about now? If everybody's happy with that we can start writing some code while I grab a sip of water. All right, we don't seem to have any questions so I'm going to move on, awesome. So the first thing that we want to talk about is attributes. Now I'm going to open up a link here quickly where we talk about attributes and what attributes are. I do recommend, I'm not going to cover this whole document but I do recommend reading it when you have some time if you're watching this afterwards I'm going to just zoom in a little bit so we can make it a bit bigger, there we go. And the article talks about what attributes are and how they work and how to use them and all that kind of thing but in short attributes are pieces of data that are stored in the block markup. The finding attributes is how you develop blocks that your users can edit so think about attributes like a little bit of data that is being stored on the block it's something that follows with the block code it moves with the block wherever you use the block that data is available you can specify the type of data you can specify, thank you Shumama I forgot to hit the link there you can specify what type of attribute it is and where it reads from and all those kinds of things we're not going to dive into all of that today we're going to cover that in a future session but basically it's the data that belongs to the block it's also, you could think about it as the state of the block that's a term that is used in sort of developer circles as the block state is the state of the attributes. Block attributes are defined in the block metadata in the block.json file so we're going to define a very simple attribute now in our block.json if I scroll down you'll see the format is basically just to create a top level attributes item and then to give it a name so in our case we're going to call it content like the code example we could call it anything we could say block content or we could say text content, whatever we're going to just use content and we're just going to make it a string type today that's what we're going to do for now so I'm going to switch back over to my code and I'm going to open up my block.json file and I'm going to pop it anywhere as a top level item so anywhere these are all top level items I'm going to pop it anywhere there I like to do it just after the name that's just a personal preference it can even go after the style element if I wanted to but I just like to put it off the name so I'm going to do double quotes there to follow the format and I'm going to go attributes just after that and then if we have a look at the example code it's basically it's using this object notation so this is how you specify a JavaScript object is using the curly braces then we give it the attributes name so what it's going to be passed around then there's another object and that's the definition of the attribute so let's go back to the code so I'm going to open up those braces I'm going to give it a name in our case content this is user defined so developer defined so I'm saying this attribute is called content and then I'm going to give it some definition and for my purposes today the only thing that I want to do is I want to make it a string type that's all I want to do for now I see Samam is copying the code there thank you so much, I appreciate that he's copied the whole thing but for now I'm just going to do type string and hopefully we'll have time to explain why we can get away with this now towards the end but that's all I want us to do for the time being okay, lastly you'll see that this category is throwing me a little area here and that's because I haven't got a comma after my end of my attribute object so I pop a comma in and now Visual Code Studio is saying yes, this code is happy, we can move forward okay, now to receive these attributes in the block we need to accept it somewhere and by default the edit and the save functions receive a number of properties through an object argument and the attributes are part of that argument so if we have a look at the block.js code we'll see here the edit function can accept arguments like any other function and so what we can do is we can give it a name here and in our instance we'll just call it props just for the sake of using what most other folks use and basically all of the properties for this block will get passed to that props object now you could if you wanted to you could say it's just properties because this is developer defined you can call it whatever you want and it will always just receive the properties of the block passed to the edits and the save function but most folks just use the props because it's shorter and easier to remember so I'm gonna just pop props into my edit function and into my save function and then I want us to have a look at what is being passed in those props so to do that we're going to use the console.log function and we're going to console log props in the edit function and what this will do is this will output the props into the developer, the DevTools console but before we do that I wanna do one other thing I want to give my attribute a default value and I'm going to give it the default value of the text that we want to use because when you load the block in the editor you would like that default value to come through somehow so I'm going to go here and I'm going to say add default and then I'm just gonna pop that string in there and I'm making sure that I'm putting a comma after the type and I'm specifying a default value and that's generally the minimum you need to get away with for an attribute to kind of work so we've specified the attributes of content we've given it a type of string we've given it a default value and then in the edit function we've set up the argument to receive the attributes in that object and then we're just logging it out to the editor and that's what we're gonna do for now so we can see what that looks like if I switch over to my browser and I'm just going to that has been saved so I'm just going to refresh this and then I'm going to remove this block there and then I'm going to refresh again just so it's all nice and clean and I'm using that MC cache and hard reload and you'll see that there you'll see that there's a couple of errors and this was something that I saw earlier when I first loaded this page so I know those errors are fine but up here you'll see here are my props being logged to the console so I'm going to make this a little bit bigger so we can have a look and see what's going on there and I'm going to move this over to the side here and you'll see that it has the name of the block there are the attributes right at the top so there's the content attribute and it currently has this value which is the default value we've specified which is great and then it has a few other things it has some on remove functions and on replace function and then a set attributes function so don't worry too much about what the other things are doing for now we're just going to focus on the attributes part of it and the set attributes part that's what's coming through there now while we're here let's also talk about block props before we talk about block props I just want to pause for a second and just check that everybody's up to speed with attributes and how we've set it and how we are seeing it in the console and if there are any questions around any of that okay I don't seem to have any questions and as I mentioned I'm kind of pushed for time so I'm going to continue but if you do have questions feel free to send them through in the chat the other thing I wanted to discuss is this whole block prop story and this is where it gets confusing when you talk about the blocks props and block props so very quickly block props is defined because we're using the use block props react hook use block props is a special function in react world and currently in the Gutenberg block editor world that does a whole bunch of things it sets up a whole bunch of functions and it automatically sets up things like the block class name the aria tab and all of those kind of things and because we are setting up the block props object here and passing it to the element what it does if we have a look at the block on the front end and if we inspect this block is it automatically sets up things like let me just make this a bit bigger it sets up things like the tab index the block ID the role the aria label the block type the title of the class so that's basically everything related to the container element for the block now our block is very simple it just has a paragraph tag and a child element with some text that's all it is but blocks can be more complicated they can have a div and then multiple paragraphs and then maybe other divs and other components and other elements inside them and the block props variable that we create by saying use block props will only affect that container tag now as we continue through this through the series of workshops we're going to be adding additional elements and we'll understand better how that works but that's what block props does if you remember from the previous session when we applied block props to our element it automatically enabled the toolbar for the block and that was because the block now had this where is it a class it had the I can't find it now here the WP block class so the minute it passed the WP block class then it set up the toolbar and the toolbar started working the props or in our case the properties are specific to just this block so use block props you can use on any block and it runs a whole bunch of things automatically the props that have passed the edit function the save function is specific to this block as we're working on it here it also does some automatic things in the background but it'll always be specific to the code we're working with and as we saw earlier it'll pass through the attributes and the set attributes function okay any questions on all of that before we start applying this attribute okay doesn't seem to be any questions so let's move on now before we start using this attribute we need to look at using something that can accept this data and allows the user to change this data currently we were just rendering a paragraph which is not great we could render something like a text area but that doesn't quite work as well as we needed to and it makes things a little bit confusing so in WordPress developer land we have this very amazing component called the rich text component and I'm going to find there's the attributes on that page so I'm going to find the rich text reference guide I'm going to pop it into the chat here and the rich text element effectively uses something that I forgot about until recently called a content editable input and I'm going to open up that link as well so a content editable input you can if you have a look at this code you can see this code is being applied to a block quote content editable true and then it allows you to edit a block quote that's a new thing that came about in HTML and JavaScript in sort of recent years where you can specify element is content editable and that allows you to then edit it so you don't have to use a text area you can just use a content editable area and so the rich text reference allows you to render a content editable input and give it a specific tag so you can say I want it to be in our case a p tag and it will then render a p tag and render it as content editable so that's what we're going to do now the cool thing about rich text is rich text exists if we have a look at this plain code here in if we can find where's rich text I'm not going to find it now am I? Let me go back to the the how to guides because that's where they're using it let's find it here quickly here we go if we scroll down and we find it here over here there we go rich text comes from the block editor package and we're already using the block editor package because we're getting used block props so we don't have to worry about any dependencies we're already using block edits in our code which is great we can just grab rich text from the block editor so I'm just going to copy this line out over here and I'm going to pop this is the very top of my code over here there we go so now we're saying creates a variable called rich text and get the rich text component from the block editor object and allow us to use it excellent so then we're going to now change our edit function so that we replace just the plain paragraph tag with the rich text element so I'm going to copy rich text there and I'm going to pop it in over there and now we've got block props and we've got the content okay now let's test this code and let's see what this does I'm going to just comment out this console log here so we've just, all we've added is we've added the props that's all we've done for now and then we've added rich text in the code at the top here by calling block editor dot rich text and we've changed it and we've put rich text in the where the paragraph tag used to be so let's refresh and let's see what that does I'm going to make my dev tools a little bit smaller so we can actually see what's going on and we're going to refresh I might have to remove the block first okay it's giving us an error which is to be expected so I'm going to remove it and then I'm going to go back to my console I'm going to clear the errors out and then I'm going to add it and there it gives us an error and if we scroll up to the top of that error it says to us that let me just get there um unquote type error children is not a function at rich text wrapper okay so what that's telling us is that the rich text component doesn't work with children elements like a plain paragraph does and if we go and read about rich text and understand how it works rich text needs a value attribute it is in the documentation but if we have a look at content editable for example content editable is not rich text but if we have a look at the rich text I think I had it over here previously let's go back one here we go I found it the other day now I'm not going to find it am I? I'm not going to find it now but anyway it can't work with children elements like we do with a regular paragraph tag we need to specify a value property now the way we can specify a value for rich text is we can pass it in the object that is being passed to the block in this case that's block props so the one way we could do that is we could change this object and we could say look we just want to pass in value and then pass in the value that we want to pass but we want to use use block props as well because that gave us the class and all those things so now we use something in JavaScript called object assign which I will find for you here in a second here it is an object assign is very similar to PHP's array merge and what it does is allows you to take an existing object and add things to it and all we want to do is we want to add a value to block props so what we can do is using object assign so it's object assign target and then give it a source so we can do this and we can say instead of just passing block props we can say object assign and we want to update block props and then we pass in a new object so it's using the object notation and we say value and then we pass it the value that we want to give it in this case we can pass in the hello JavaScript world but I think I've just copied or something I shouldn't let me just move this out the way, yes I have there we go hello JavaScript world and then we can get rid of this child element at the end there so there we go so we're still returning the same element now we've changed it from paragraph to rich text and then we're taking block props and we're updating whatever's in there and we're adding a new item called value and the value has the string that we had originally so now if we refresh that code we shouldn't see that error again so let us refresh here okay we're getting a different error but that's not related to this so that's cool so that means we're not getting an error so now we're using rich text in the way that it wants to be used instead of passing it the third parameter say in the element which is the children we're passing it the value because the value needs to be updated and if you have this in your browser you can now edit your code okay you'll see that it's giving me an unadjusted change error which we'll get to in a second but at least it's rendering rich text and I can edit this code I'm gonna pause for a second if anybody's coding along and they're having any problems or they need to get any questions otherwise we're gonna move on to the next step keeping a drastic eye on the time here so that we don't run out of time okay so now this area here says to us that your on change adjusted on change is not a function and that is because rich text also requires an on change function to be set up so that when you make a change it can do something with this new information and what it's expecting it to do is be able to save that back to the attribute value so let's implement that in the code so the first thing that we can do is we can use from the props we can replace this content here I've done it again sorry I've got things on my screen that are making me not be able to see things like I want to we can update this text with props attributes and then our content attribute to be specified so that'll take the default value hello JavaScript world and we're gonna change this from the block.json so that's passing that to the value then we need to specify the on change event and we can do that in the same object that we're passing in the value to apply it to block props so to be able to make that a little bit readable I'm gonna move things onto new lines here so I'm gonna move rich text to a new line object assigned to a new line and then close that over there and then I'm going to do this and I'm gonna pop this object down here just so it makes it a little bit easier for me to read and I'm gonna make that on a new line and that on a new line again just to make it easier to read so all I want to do now is I want to pass an on change event or an on change method into my object that is being merged into block props so the first thing I do is I specify the on change which looks like that and then I need to give it a function that it's going to be called when the content changes and in our case I'm just gonna go on change content I still need to define this function but that'll do for now I also need to add the comma between the object attributes so that I don't get errors so now an on change is specified so the rich that error will go away so every time the editor, sorry the rich text component gets changed it'll fire that on change but now I need that to do something so I need to specify that function at the top here so up here we can say function on change content and then we can do something with this content and what is going to be passed is some updated content or some new content I'm just gonna say new content so whenever I, and let's actually just log that to the console so we can actually see that working so log new content that's all I want to do for now okay, so we specified an on change event handler basically it's whenever something changes then file this function called on change content on change content function will receive the updated value and simply log it to the console okay, so let's have a look at that so again, if we refresh here I didn't do a hard refresh, did I? Let's do a hard refresh, hard reload in this case okay, so the errors that we're seeing are not related to our code which is great if we hit there and we hit change there you can see the updated code coming through in my console and I'll be honest this is really cool to watch happen so what that means is that new content variable is receiving whatever's being changed in our rich text component which is perfect so now we can write that back to the content attributes in the block attributes and how we do that, if you remember earlier I mentioned that set attributes function that gets passed in props we use set attributes to update the content attributes so let me show you how that works so first of all, we grab props over here and we say props and then set attribute was passed into props so we can set attributes and that's a function that belongs to that props object and then the content that we want to change is the content attributes, it's called content I'm just checking my code here very quickly one second folks, I can find it now there we go, okay so all we have to do when we use set attributes is we pass in an object so this is very similar to object assign we pass in a new object with the name of our attribute in this case content and whatever we want to update content to in this case, the new content being passed to the unchange and we could make, we could do now what's cool about this is we could do things with new content, we could add stuff to it if we wanted to, we could go off and fetch data whatever and then update the content so if we do that now and then there, if we load this into the browser we will not see anything different but the attribute is being updated so what would be very cool is to actually be able to see this so what I'm going to do is I'm going to console log props.attributes at the top here actually let's do props.attributes.content so we can see what it was when it loads and then let's console log props.attributes content after we update it so we can actually see if it is being updated so there it's, this will log it once the edit function fires and then as soon as we update it then this console log will have it so let's have a look at that let's remove this again let's do an empty cache and hard reload and there it is and let's just hide all of those for now and let's see what happens so there the edit function is fired so that's changed and then we can see the new value and we can see it's on block seven the new value is now whatever it was and if we change it again it fires and fires, fires and that's the new value so every time we're changing it that attributes that is loaded with the block is being updated it's doing what we wanted to do that's great but now we need to save that somewhere and that's where we do that in the save function so in the save function we're going to do similar things to what we did here in our edit function we're going to pass in the rich text but because we're saving we don't do just the rich text component we do rich text content so it's basically just the output of the rich text component we can do the same block props and then we can also pass in the same value so we can do the same object to sign stuff over here so what I'm going to do is I'm going to put this on a new line so it's easy to see and we can take away that and take away that and do the same block props object to sign and give it the same value props attributes content and we can remove the on change because we don't need any on change things happening in the save we just need to receive the content so what that's going to do is it's going to render the element and save it to the database with the updated value so that when we refresh it on the front end we will see the change if we look at our code now and we change this hello JavaScript world and we've changed it all the way down to there and then we say save this and then we say preview this in the new tab it's still using all the original content so it's not passing it to the save function but now with this new code passing the props to the save function and updating the element with the rich text content and assigning the object with the new value it'll apply it to the save function so now if we go back here and hard reload okay now we're getting some errors now the reason we sold that error is because we had a previously saved version of this and WordPress is going hang on you saved it with a previous value and now you're coming with a new value and I don't understand that so that's one of the reasons why I always will remove my blocks from the page and I will save the page and then do the hard refresh if I'm in development I'll always generally clear the block out so that I don't get any of these weird save functions okay so that's fine all those errors we expected so that's great so now if we add the block there the block is added with the default values we're still seeing those console logs that we left in the edit so let's update this and say something like hello JavaScript world let's say edited in the block editor we're seeing it all fire and go off and do its thing and there it's saved so now if we preview this in the new tab now we see edited in the block error in the block editor now you'll see there's an issue with some styling going on there and we will have a look at why that's doing that in a second but at least the attribute content is working it's saving the attribute where it needs to save okay now the reason that that error is happening is because we also need to tell the element what tag name to apply if we have a look at the code up over here here we go we just specified rich text but we didn't tell it what kind of element to create whether it should be a paragraph or not a paragraph whatever the case may be so what you also generally need to do is you need to specify a tag name which you can pass into this object that's being passed to the block props so let's do that so we'll make that a paragraph tag and we'll need to do the same in the in there as well and then that will find the classes and all those kind of things that make things work so if we update that now we should see this working what I'm also going to do is I'm going to remove all of these console logs because that's going to get a little bit annoying I'm going to remove that there quickly and I'm going to remove that one and I'm going to remove that one there and then let's go back and test this so if we empty and hard reload this now we should see things start working okay we're again getting a validation error because things have changed that's fine let's remove it and refresh if you get that block validation error while you're coding it probably means you just need to clear things out and start over okay those errors we've seen before we know they're not to do with our block so let's add our block again and then let's edit it and now we should when we preview this see everything working on the front there it is Hello JavaScript world edit it in the block area so the reason that happened is because we had to specify the tag name we had to tell rich text to render a paragraph tag in both the edit and the save and then it renders the same content editable area sorry element with the same classes and then the styling all works so that is a requirement whenever you're using rich text you do need to specify that tag name any questions we've got about 13 minutes left so we might do some cleanup afterwards which will be good but any questions on all of that before before we wrap up I'm literally just editing some notes of mine here because I picked up an error in my notes for the session okay there don't seem to be any questions so just to refresh we pass we don't pass we create a variable in the edit and the save function to receive the blocks properties which includes the blocks attributes and the set attributes function we then update the element render to use the rich text component and to do that we need to assign both the tag name and the value and the on change event handler to the block prop so that we can use those things the tag name in this case was simply a paragraph tag we could have made that a div any kind I think there's a couple that rich text can handle let's have a look at the doc yeah it could be anything it's okay it can be set to any block div h2 paragraph whatever you want in our case we're working with a paragraph tag the value will be the value of content so when it loads the first time it'll be the default value if you save it and it loads it after a save it'll be whatever's in the saved value and then we specified the on change content function so it's take the new value when it gets edited and update it based on that and then in the save function we set up the same props set up the same rich text in this case it's rich text content because we just want to render the content and then we specify again the tag name and then the updated value now the last thing I just want to mention we probably won't do some of the other refactoring that I wanted to do but the last thing I wanted to mention is that when you are creating your attributes in the documentation about attributes it talks about let me open up this link which I'll copy into the chat now it talks about the fact that attributes have to have a type or an enum but they can also have a source and they can have a selector and then they can have an attribute defined so this is a URL attribute it's called URL and it has a string type its source is the attribute the selector is the image tag and then the attribute is the source and that gets confusing and all that means is when you are using attributes the attributes content can be stored in different places in the block if the block is like in our case it's a rich text component which renders a paragraph tag the content is effectively just the content of the paragraph tag so the source the source means where do I read that data from and in this case because the paragraph tag the source is the HTML of the paragraph tag which is the text and then the selector is to say well which element inside of my block must I read the source in our case the HTML from and in our case the selector would be the P, the paragraph tag in this example that you are looking at here because there is an image tag you can also specify an attribute that it needs to read it from so in this case it's an attribute source in other words reading it from an attribute of the image element and the attribute that it needs to read is the source attribute now in future sessions I'm planning on doing one where we load a background image and so we'll then need to specify that attribute and use this and we'll deal with that there but that's basically just telling WordPress what when we load this attribute data where do we get it from within the element so it's a good practice you'll notice we didn't do it in our in this code but it's a good practice when you specify the type to also specify the source which in our case it's an HTML source and then also specify the selector which in our case is simply the paragraph tag now the reason it worked earlier is because we just had the one paragraph tag if you had let's say a div tag and then a paragraph tag inside of that div tag and you had this content set up like that it would look for the element with the paragraph tag for the source data not the div tag so it becomes more important when you have multiple attributes set up in our case when we just have one set up we don't need to worry about that too much because it knows to read it from the main paragraph but it's a good practice to get into specify the source specify the selector so that it knows where to read it from okay that is my bit for today I'm not gonna have time to do the other things that I wanted to do I'm gonna try and record them after the session and add them on and basically just doing refactoring and that kind of thing but this was a slightly different way of looking at using rich text using the attributes as I've mentioned in the workshop I have documented all of this in the read me of the GitHub repository as well so if you go to, I'll copy the link now let me just get it here and it's the WP in JavaScript if you click on any one of the three folders which is the different steps we're working through it now has a read me document that you can read through and it covers all the things we've covered in the workshop and I was actually referring to this as my notes when I was covering through this so if you're not sure of anything everything is in this document all the links are there all the examples are there and it explains how everything works and shows the possible errors that you might see and what they mean so that is my bit for today I think that's where we're gonna wrap it up does anybody have any questions, any comments anything they wanna add before we call it a day no problem, Linda thank you as always for joining me it's always nice to see familiar faces so the plan is next week or hopefully next week we're gonna add a few more attributes to this block the goal is to add an attribute so that we can manage the styles so eventually I want to do away with the style sheets and we're gonna manage the style in the block so we're gonna manage the background the color and the padding as attributes and then as I mentioned as well I want to add a background image to the block because that'll go dive into the deeper element of how the attributes work and give you a good understanding so we're gonna change it to like a div and the div will have a background image and then there will be the rich text inside the div so we're using multiple elements inside of other elements and those kind of things that's the eventual goal the other goal as well is also just to work through all of these steps in the blocks creating a block tutorial so we're gonna be talking about toolbars and sidebars when we do the future attributes in future sessions we'll be talking about block supports we'll be talking about dynamic blocks how you can render them in PHP yes I can certainly paste the get link there for you I do try and keep this up to date as we finish each session so you're welcome to have a look at that code check it out, play with it, fork it if you find any bugs in the code please log them as issues and I will update this code this is going to be a living document a living piece of code that we can use through these sessions and you're welcome to grab it at any time and use the code there it's completely open source anyway as I was saying we're gonna also look at block supports and dynamic blocks we probably won't cover generating blocks at WPCLI we're probably gonna be looking at nested blocks at some point using inner blocks we probably won't extend the query loop block that's a little bit outside of the scope of what I want to achieve in these workshops but that's the eventual goal is to kind of cover all of these things but also build a block that actually is something I'm still thinking about maybe it'll be like a call to action block or a header block that if you want to you can even use your own projects as a basis for building future blocks but that's my bit for today folks thank you all so much for joining me today this workshop will be going up on WordPress.TV tomorrow I was going to override the previous one with this one but I think having them both is a good idea because there's two different ways of looking at it so I'm gonna look at maybe adding this as a new one we'll see I haven't quite decided yet but anyway thank you all for joining me it was lovely to see those of you who are here today to my American friends who are here enjoy your Thanksgiving later on this evening and I will see you all again next week