Creating complex field widgets on Drupal

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
okay so hello um today we're here to talk about how to create complex field widgets on drupal um i'm pretty happy to be here i'm very happy um to have all these people here too um this is my first time talking in the background like in sessions so i'm pretty excited about all this um so thanks for coming welcome um this is a link to the slides you can see it in the top in the bottom right um it is going to be there for around three slides but if you can get it i'm gonna put it in the chat at the end of the talk um but yeah welcome so who am i hi my name is spinach um you can find me at like darisa in almost everywhere um i am from costa rica i live in the pacific coast i live like one block away from the beach but i never go but i love it and i have almost a zoo in my house so many dogs and cats and you'll see here my friend feels good um he usually comes in when i'm talking and start biting my headphones so if you see that it you know it is that we can't do anything oh yeah okay i'm a drupal developer um i work as a triple decker developer in sodium niti which is a costa rican company and we are an agile full service web agency with a human first collaborative approach in design and excellence in delivery we are a group of passionate people with who wants to make the web a better place and um we we're really focused on humans and experiences and that's what we love to do i've been working with joopa for about i think almost six years now and a lot of that time has been working with deacon deacon is a community dream and free and open source opener platform that gives organizations and individuals ultimate freedom to polish and consume structural information so why i'm talking about deacon well a part of it being a big part of what i do um also this stuff comes from that it was a problem that we were facing in the deacon new version and we found out that the best way to achieve it and to solve the problem was actually creating a custom widget um so this is what this that is where this comes from so what are we going to cover today first um just for setting the base we're going to talk about things we need to know before starting to create widgets which are fields in rupa render arrays and annotations then we will go full hands-on on custom widgets where are they when do we need them um when do when we don't need them and then i'm gonna tell you the story of the problem we're having and how we solved it um so let's go first um i i assume some of you already know some of these stuff so i will try to cover it quickly um but yeah i believe it is it is good to have like a common base just in case so things we need to know fields um i know we've all everybody that works with drupal have interacted with fields so they are um individual components that make every content type in drupal unique right so for example in in in most in all the content types we have the body field in a title field and we can add as many files as we want we can have an address an email and phone fields we can have tags we can have anything right and all this stuff is basically powered by a big part of drupal which is the field api this field api is what is in charge of defining all these components um of drupal the field api is made of three main components which are the field types fill widgets and fill formatters um so at the beginning it's a little bit hard to find a difference but in practice it is just like the fill types is what allows us to define the type of data that is going to be stored so that way we can say okay this is going to be a string this is going to be a number this is going to be an entity reference this is going to be a date and like that the fill widget is actually how the field is going to be rendered in the form right so how is it that the user is going to interact with drupal to be able to save something in the database and then the field formatter which is how the field is actually rendered for the final user so um widgets and for marios at the beginning for me it was a little bit weird i i didn't understand but it is basically that widgets is for farms for mars for the final presentation of the items so for example in the case of the text which we can see in the screenshot we have an autocomplete filter for adding tags in there and then we have different admirer which is how we are going to present it so for example with the tags we have different ways of showing rendered entities and we can show it as plain text we can show it at links um and those are for manners um so the main thing here is that the three items that we're talking about they're all plugins and for defining each of them we need to create a class each of these classes is going to have annotations which is what helps drupal discover the plugins and also um this classes should return a render array in order to render the item as is so this is why we're gonna cover these two items so first render arrays um what are they they are basically the building blocks of every single drupal page okay they give us information about the data that we want to present and how we shall present it they give us hints about that so um to in order for drupal to be able to know how it's going to be the rendering we need to give them this kind of arrays this running basically means how are we going to transform from arrays to html markup so how does a render array look like it'll be something like this we simply have an array which is an associative thing with keys and values and here we can see the content or the data and the properties so the the content can be there as nested already and the properties is the are those elements which has the hashtag at the beginning and that is what tells drupal or what git what gives drupal the hints about how these content should be displayed so that's it there is a lot a lot more to say whenever i raise that um you can look at it in a drupal documentation and this is like the basis so the annotations um every clash every every plugin class should have an annotation and these annotations are basically used for registering employment and describing the metadata of those plugins so they're basically a structured comments which give information about the class that we are creating so this is how an annotation will look like you can see um the first element is actually just a comment like the description of the plugin we are creating and the actual um annotation starts like in line fourth i think um when we see at fill widget so usually we have add in the type of the plugin and in this case this will be as a widget um i took this example for from the boolean checkbox widget which is in core and yeah basically it has some keys and some values the annotation syntax is using doctrine but even then we have to follow some drupal standards so for example at the end of each value we need to have a new line and when we have our rays we need to keep adding the trailing comments at the end and that kind of stuff but it is basically um doctrine we'll go deeper in the description of the fill widget later on also if you have any questions um you can type in in the chat and and i can answer um so yeah now that we have talked about all these three things we can go deeper into custom widgets we know that a lot of things in ruble are made via the ui but sometimes what football gives us is not enough so it is then when we have to try to see if we should create something custom in this case we're talking about custom widgets they are of course created in code um and it is interesting because they can be a combination of other existing arrays i mean existing widgets that we have but with some extra functionality or maybe they they are written from scratch because what we have is not enough for us and we need to do something completely different or maybe it is a mixture of both and we are going to extend an existing widget to add more stuff in it so custom widgets are are very powerful and we can create a lot of stuff with them though not always are needed um we we don't always need to do this for example if what we want to do is just display the uh alter the display of an element then probably we don't need to do this like if we want to change the label or something like that we can just use a form alter even to add extra submit functions um to our forums we don't need to do a custom widget for that we can do it in a formatter same without any extra validation functions or even showing fields conditionally not not necessarily we want we need to create a full custom waiter to do it in the in that case um we could do states api or something so this takes us to when do we need to do this okay um basically it this is a good question because drupal provides a lot of widgets and it is pretty hard to find them all out so um the thing is drupal has a lot of things but sometimes that is not enough so we will need to exit take a deep breath and try to find out what do we need so i'd say that in order to create a custom widget we should figure out what is it um that our necessity is for example i think that storing data in that specific way and make it easy to use and not our primary users that specific thing maybe something we can do with form of with with custom widgets so for example the classic example of how to do a custom widget will be like the color picker widget um [Music] so why is that a good example because we need to save the thing for example in an excitational code but we need the user to put something valid there so it is easier to have a color picker and then save the value as the xml code and that's it another example is um actually something we we had in beacon um for example we have some field that we need to save as an url but we also need the user to be able to upload a file or link to an external file we don't have a widget in drupal that allows us to do that um we have something that allows us to add an url and we have something that allows us to put a file upload but not something that allows the user to choose one of the two and save it in the same field so that's a good example of when a custom widget can be done um other option is what we're going to do here which is like having multiple fields inside of another field um we're going we're going to go into this um really soon so how do we know that what i need to do is not in drupal okay there are so many with this in drupal and sometimes it is hard to find existing widgets i would recommend first checking um the core and the control module have you have installed and in order to do this you can first check drupal console um with drupal console you can just run one command and it will return all deployments that are filled widgets in your current installation including all the control modules you have or just the core and and the core i mean so um it is fairly easy to to know it and you can test and you can see um if if something about that works the the module i mean the command will give you deployment id and the employing class so you can go deeper into the code and find out uh what you need even this will help you this will help you to find out if you need to do some more customizations on the top of one of the existing widgets and that's pretty cool and it is doable so um there's that so what was the problem we had in indian basically we have one see what we we have one content type which is called data and this content type has just one single field which is called json metadata um we did this because um we are focusing the schemas where schema first this is a schema centered platform now and we don't want the users to have to come to the field ui and change the different fields and export all the configuration and everything so the developers or the people who who is in charge of the data um can just come to the schema and update the thing and then we just save it in one single field um it is pretty asc to do and easy to handle most now that we are api first but it is a problem for the users because imagine a user coming here to change the title of the data or changing the the modified date or or the temporal date or the name of a distribution i don't know it will be hard for them they will need to know json in order to do that so we started using a library called react using schema form which did basically what we needed which was actually be to build a form based on us on adjacent schema it was pretty cool but it will still give us some problems so one of them was we had to build a different ui so it was not so intuitive for users to go there and do the things that they needed to do and the other thing is we needed more powerful features like the date speaker that library didn't have that or or the other element i just told you about the one with the file upload and if in the in the url field and save all in the same url so um that kind of stuff was being super difficult to do and we said well drupal has the form api and it has a lot of stuff there and it is actually pretty cool and pretty stable and pretty maintained so why don't we go back to rupaul and that's what we did so our solution was to create this json form widget so how do we do this basically we need to take five things into into account which are where is the class going to be located where is the name space it show has well where it should live the annotation the actual class and the settings so for the location it is pretty easy um we need to put it under the name of our slash src slash plugin slash field slash field widget and inside of that we shall place our our class so in our case um the class was called json farm widget and that's the the location where we put it under json from widget and all the same items as we have it in the top of the of the page here i i mean i'm sorry and and that was it so what was next defining the namespace the names is actually where the class lives so again it holds the same dimension almost um in our case we just had to change the module name to json from widget and that's it for our recipe and what about the annotation for creating fill widgets we need the annotation to be something specific there are three things that are required in order to have an annotation for a field widget and having trouble be able to discover the plugin correctly and those three things are the id which is basically the machine name let's say of the widget that we're going to have then the label which is the human name of the element and the fill types that this widget supports so this basically means that if we have a field that is of type string long we could use this widget which is exactly what we needed um so once we're in this point we have the class available right the class need to implement the widget interface which is like the interface drupal has for this kind of stuff but also drupal give us the widget base class which is a base thing that already has a lot of things set up and we can just extend from that and overwrite what we need so in order to create a widget we just need to have the form element um the form element is is the required thing and it is also where the magic happens it is via render arrays you can add here whatever you want and build a farm so basically this is how it will look like and [Music] inside of this bit is where you will get as creative as you want so you just need to build the render array and return it here for example um that string text field widget only has one element and this is the basic thing right so this looks like this and that's it but we can also have multiple elements inside of our render array so we could have this text field and then also another thing which is going to be um a file file upload and then another thing that is going to be a date figure and then we will need to process all that to become one single thing that is the thing that we're starting um so we're going to look at this pretty soon i promise in order to have the settings form this is an extra setting which was the schema because we want the users to be able to define what is the schema that is going to be used to build the thing so for example we used to have a schema for adjacent schema for data sets and another json schema for publishers and at the end the content type is almost the same it just has one string long field that has json metadata in it but it's actually different because the data sets you'll have some fields and the publishers will have other fields but depending on the open data schema um they will be different so this is what we were accounting for and what do we need to do there are three things first we need this to we need to set the default values for the schema then actually create the config schema and finally at the forum so for setting default values it is just a matter of using implementing actually the default settings method and here we just need to return the name of the properties or the configurations we need to have in my case it was just something called schema and also return this thing with the parent default settings why is this just because if you are um extending another another widget that has already some settings and you need to append other settings then this is the best way to have both things there and not miss what what the parent class give you so that's one thing um after doing this we need to create a config schema and this config schema is basically a file inside of the folder config inside of the um inside of that have a folder called schema and in there the file um so this is what the content of my file was it just needed to be filled with that settings and the name of the module to say it is that and then i'm looking for the schema we were creating once we have this we need to actually add the form and again this is just a matter of um implementing the settings form uh method and in here we just need to add again a render array displaying um giving drupal the hints about what it needs to display so in this case my schema field in the settings form for this widget is going to be just a text field where people is going to put the name of the schema in my case um we already have the schemas defined somewhere else and so i just needed the people to put their the name of the schema that we are going to retrieve and using a service where we're trimming that but if you want to do something like this like you could put there a string long again and have a text area and put the whole schema inside of that that that could work too um or get creative it's fine um so yeah this is this is what we did and at this point um when you go to the manage form display for the data set i mean for the content type you want to apply this to um this is what you will see now you have the widget settings form and the field for the configuration so people should put here whatever schema name it is and we will retrieve that schema and build the form based on it so yeah what happens if you close um the element if if you just put the name there and click on update you wouldn't see what you put in there so there is an extra thing which is adding the settings summary if you want to have a setting summary you just need to um implement the semi summary method which again is just a renderer a random array which has the name of what you need to which has the data that you want to display so this is how it will look like once you close it now it has um the the summary here because the user put in data set so that's what we see now so for now this has been like simple things and in order to make it complex we need to be creative but basically what we need to do is alter all we want in a form element and build their arena array with all the elements we want and then um this is the tricky part because probably creating a render array for the form element is is not so hard depending on what we need but then if as in our case you are you need to put there a lot of fields and then save it in just one single thing um you need to do some handling of the data and it's handling of the data needs to be done using the implementing the method extract form values this function allows you to take the values from the submitted data process all that thing put it as you need and then um drupal will know what to do with that that that is the actual value of the field you are putting so in our case we wanted to show a full form with a lot of fields and have the users be able to put every single thing in there once they click on submit it should all be saved in just one field which was the json metadata so let's see it i'm gonna stop sharing for a second to change um to change when i'm presenting and okay i think you can see my screen now so basically this is what we have this is where we will change the thing and this is the code okay so this is code um here you can see um the location of the things i'm gonna close this a little bit you can see this is where our schema was created and this is where all the magic happens so we have the namespace defined as i told you before we have the annotation here um so as you saw we have the three required elements which are id labels and field types and we're extending it widget base um in our case it is like this because we needed to have a completely different thing so um i am joined dependency injections because i needed to have another service that we are using and just that you can see here the default settings thing being implemented and a settings form and a setting summary and all that it does is for us to be able to come here look at this json metadata which is a string long thing and make it be a json form so if we do this we need to change the actual schema in my case i'm going to put here data set i'm going to update that and i'm going to save it so when it was the other widget this is how the form looked like i'm sorry i haven't updated my drupal site this is about practice please update your sites um but yeah okay so once it is saved if we reload this page we're going to see we have the full form so this is quite easier for users to be able to come here and update each of the things we have so how did i did this basically i just use the form element function in this function what i'm doing is bringing the um default values of of what is like bringing the values of the node what is already saved in case there is something safe um if it is new of course it will be an mtr right this default data but basically i just called a function called get json form with all the information i needed to build the form with so this get json form is what actually does my magic um so here i am basically just retrieving the schema in order to uh build the form and once i get the schema i am iterating over the properties it has so i'm just going to show the schema real quick well this is a big schema it has a lot of fields so for example um it has all these properties it has a property called type title identifier and you can see here that we have information about what those fields should be okay remember that the json schemas what what they do is actually help us validate json so um if we're already validating against that we are now trying to also build a form based on it so here what i'm doing is actually iterating over those properties and getting the form element necessary for each of them so the form the get form element these these other functions are private because they're not really used anywhere else um but it is what we have right now so this getform element actually takes in the type of the property we were looking at so for example for type the type is a strong for title the type is also string the for identifier is also string but for example for for the field um let me find it for the field publisher it is actually an object so the the main elements we have in this schema are objects arrays and strings so i just got different um functions for each of these type of items so we can actually print or or specify establish what is their render array for for them in this case um the handle string element what it does is basically set an element that is going to be of type text field so the widget that is that it is using is a text field but then we add a lot of scene a lot of stuff in based on the other properties of the element so if the property has a title then we append a title to the element if it has a description we append a description and that's how we we are doing things for example if you see this element here the frequency it is a string but it has a property called anim inum so what i do is if it has this property then we convert the item to be a select list and that's how this is all being handled um just join a lot of conditionals checking what is um that we need to print and this not only works with this schema it should be able to work with other schemas as well in our case this is these are like the three items that we always have like object arrays and strings but if we are going to build something and that has different types and we can also add it here um i think it's fairly easy um so the handling of everything is complex for example how we added the arrays or how we added the objects was kind of interesting so for example i'm going to show you the object thing um okay so here it is so the function for handling the objects is just a function that has a feel it could be a field tech um i forgot the name well a field group something like a field group i forgot the name right now or we can have also details or that kind of um elements so if you see this for example the organization which was an object we have it as a as a details element here a field set just remember it it could also have been affiliated um so here we make the field set and then we start calling again the god form element with the specific properties that the publisher has so it is just a matter of getting deeper and different levels of nesting but um we can add the things the more trippy the most tricky part here was actually with the arrays because we needed to be able to add more elements and remove the last element that was added um so it was it was kind of interesting so in that case for hanley narys um this is what i had to do there's also something interesting here because we needed to handle simple arrays but also complex arrays what are these each of these things the simple arrays are something like the categories like we have just one text field or number or whatever it is but just we add items one by one okay so we add one category and then we add another category and the category is just one property same thing with tax here but what happens if what you have is an array of objects that is going to be a little bit different because you need to um add each element and then call again the things to build the elements that are inside of that object so building the arrays in general was a little bit more confusing um because we needed to handle like the different deltas and the different keys um because it is a multi-value thing and yeah so what we did for this was basically add some um ajax callbacks for each of the items and we needed to um have those callbacks somewhere that drupal could see them so i found out this gave me a lot of headaches but we found out that um when we wanted to add a callback here it didn't work it wouldn't work actually this one they wouldn't work if they were inside of the form widget or of the custom widget class i'm not really sure about why but if you need to do that instead of um your custom widget the best thing you can do is to have the itex callback to be inside of your class but the submit callback to be outside of it so i just had the submit callback to be in my dot module file and in here i picked up the name of the item we were adding and check check that against the triggering element to make sure we we are adding the extra field to the right field so for example um when i have categorian text if i click on add one more tag that we actually get the other item here and not here or not get them replaced so in order to do that um i think this is a little bit confusing but in order to do that what i had to do was to set some values in the form state for example here we were adding the elements and how many elements there were so if we didn't have elements at the beginning because it is we're adding a new element then we just put a value of one to be able to print one field and if we already have more things which is what we do in these other callbacks in the dot module we increase the amount of items depending on what was the triggered element really triggering an element um then we bring that up here and build that amount of elements so that was one of the confusing things and the other um was uh actually processing the data so in our case we had all these fields and we needed all of them to be translated into one json so it is then when i had to use the um extra for extract form values which is this this function here and here we just needed to go over each of the items we had based on how we build it and at the end once we have the data out the data already built with the elements we needed um we will just translate that to json and then set the value to the items and then filter or remove the empty things and finally set the element set the values actually in into the right place in a form state so this was one of the most difficult things but the extra extract formaldehydes is what actually let us um process our data and and flatten our data into what we really need to store it in the database so i know this bit is um a little bit confusing but i'm confident that with that new new items can can be done this work is going to be well it is open source so um i don't know if i put the link here but here this is where mario lives right now it is part of the deacon but it will soon be something outside so if somebody wants to contribute you're you're pretty welcome there's a lot of things there's a lot of work to do still and we're open to contributions so yeah um i'm not sure if there is questions about this i know there is but we are almost out of time so in case um you want it you can ping me or talk to me and anywhere anywhere any place like i'm i'm in twitter or i'm also in football art so you can tell me i'm looking at a question let me see yeah okay so max is asking if in my case the data still just getting save it to the database as a single text fill and yes that's totally true um it is still a single text field so if you click save here or you go to view what you will get is actually just um once it loads my computer is weird lately you get all the json and it is just one single thing so um i know sean already put the link to it but i will put here also the link to the to the module directly because it is in another branch it is not yet in in master branch but you can you can look at it there um again there are still some things that need to be fixed there i'm still working on it but all control all contributions are are welcome and yeah um you can find me on on the drupal slack too or in the background slack as dariza i think nobody else is that easy so yeah um you're to any page loading issues with the extra form elements for the larger the json is okay so um [Music] i think we haven't got into big issues because but i think that's mainly because the items are pretty simple i've noticed uh it gets a little bit slower when we have the ajax callbacks um but yeah i think that's like the only thing i will i will say is is making it slower we call yeah it will be a full country of drupal module um someday hopefully soon um right now it is inside of the deacon because we are we need some decant parts to make it work for example the the schema retriever but we're working on getting it out and and be something separated um so yeah i think this is it so thank you so much for being here again keep in contact um i'm happy to talk every time and yeah thank you so much
Info
Channel: Bay Area Drupal Camp
Views: 913
Rating: 4.8400002 out of 5
Keywords: badcamp, bay area drupal camp, badcamp 2020, drupal
Id: 9Tjtm5iyDu0
Channel Id: undefined
Length: 43min 29sec (2609 seconds)
Published: Sun Oct 25 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.