So far we didn’t write a single line of code but somehow managed to get a lot of things done. Usually, it works like this only for quite simple applications doing some standard stuff. As soon as you need anything fancier or less standard, you’re looking at writing some code. So, let’s scratch the surface of this very extensive topic.
Events and event handling
Let’s look at some very simple example, and list all the events right here. First, a user double-clicks on this Product Catalog item. Then, the Platform opens this item form. Next, the user changes the Units of Measurement field value. And, eventually, the user clicks on “Save and close”.
Now. To allow us to customize this functionality, the Platform exposes for us so-called events between these major happenings. These events are the places we can insert our source code in. Let’s see what exactly we have on hand.
First set of events happens before and during the Product Catalog item form opening. If we look at the form’s properties we will see them right down here: OnCreateOnServer and OnOpen.
If we click on the event we’ll get into the object’s module and here is our event handler - the procedure we can write our source code in.
But back to the example. Next, the form gets open and the user changes the value of the Units of Measurement field. Let’s check out this element events and here is the OnChange event that happens at this point.
Then, the user clicks “Save and close” and this triggers a whole lot of various events. First bunch of them live in the form. They are the write events and the form closing events.
Besides that we have some quite similar events on the Metadata Object level. So, if we open the Products Catalog metadata object module, there will also be the BeforeWrite and the OnWrite events. I also can click any of these and write my event handler here.
Why there are pairs of similar events on the form and on the Metadata Object levels, anyway? Hold the thought, please. We’ll get back to it later.
So, any coding in 1C:Enterprise always starts with an event. The events are the places the 1C developers can insert some source code in to modify the application appearance and behaviour.
Need to change the default behaviour of the system? Look for the appropriate event and write the event handler code. Whenever the event happens, the Platform will run your handler and do whatever you have implemented.
This is how it works.
And one more thing: all the events are predefined by the Platform. We can handle them but we cannot add a new event wherever we want it.
There are also some events connected to the application as a whole. They live here in the Application module. There are the events that happen when the application starts, when the application finishes and so on.
From the script language syntax point of view, the event handlers are just procedures you need to implement. So, this is what 1C script procedure looks like. It starts with the keyword Procedure and ends with the keyword EndProcedure (both of these guys are mandatory).
After the Procedure keyword there must be the space and an arbitrary procedure name, followed by the round brackets that can contain the list of procedure parameters. In the case of the event handler the set of parameters is predefined by the Platform.
We can use the handler parameters to get the operation context and to control what happens next.
OK, now, let’s write some code, shall we?
Here is a task for us to start with.
When I open the Product item and change its type to Service, there are still the Brand and the UOM fields that don’t really belong here, do they? So, I want these two guys hidden, if I select the Service product type.
So, Step 1: find the event we need to use.
This entire action happens inside this form, right? So let’s open it in the Designer. Here is our ProductType field and here is its OnChange event.
OK, that was easy. Let’s just click here and write some code, right? Except, the Platform is asking something. Again.
OK, let’s take a closer look.There are, actually, the code templates the Platform can create for us. And the difference between them is all about the client-server interaction, so let’s look at this part first.
So here is the deal. The Platform utilizes the three-tier architecture - an approach that recognizes the three isolated layers of the application: the client, the application server, and the database server.
These architecture is the one-way road: requests always go downstream only. The Client can call the application server, and the application server can call the database server. But never the other way around.
The form lives in the 1C Client. The data lives in the database server. Whenever the form needs the data, it has to ask the application server to get it, because he is the only one who can do that.
The form asks the application server using the form’s own module, that’s, in a way, sits on two chairs. It can have some procedures working on the client side and others - working on the server side.
How does the Module know the client-side procedures from the server-side ones? Well, it actually doesn't. So you need to tell it.
If you want the procedure to run on the client side you want to put the &AtClient compilation directive right before the procedure declaration.
If you want to try it on the server side you want to put the &AtServer directive. The &AtServer procedure passes the entire form to the server and make it accessible for the procedure
So the server-side procedure can read and change anything in the form object - attributes values, form elements etc.
When such a procedure finishes, it passes the changed form back to the client. This form passing back and forth takes time, so you want to do it only when it’s really necessary.
Otherwise, you want to use &AtServerNoContext compilation directive to speed up the app and reduce the resource usage.
So. Let’s put it all together.
First, you find the form event you want to handle. Then, you bind the event with the &AtClient procedure. If you don’t need to access any data, you stay in this procedure and do whatever you want within the form. If you do need the data, you call either &AtServer or &AtServerNoContex procedure, depending on whether you want to work with the form on the server or not. And then you access the database data from any of these two.
ОК. Now let’s clean this up and ask the Platform to create a handler for us one more time. Now this question is quite clear. Do we want to work within the form, or we need to access the data? And if we do, do we need the form to be accessible for the server or not?
What we actually need is to compare this form attribute with the ProductTypes enumeration value. The attribute lives on the form, but all the enumerations (as well as all Catalogs, Documents and Registers) live in the database, so we gonna need a server call.
We’re comparing the only value, so we don’t want to pass the entire form to the server and back, so this is our choice. And here we go.
This is our client procedure that will be called as soon as the ProductType field value is changed. This client procedure calls the server procedure, that has an access to the data so we can get the Enumeration value.
And now we are ready to write some code.