It is difficult for the programmer with a little experience on the 1С 8.2 platform to understand: BeforeWrite, OnWrite, AfterWrite, on the server, on the client, in the form module, in the object module, ah-ah-ah-ah-ahhh!!…..
This complex feeling of misunderstanding I had at first too. During learning and a real experience this crib was created whose purpose was “to unscramble everything” in order to have a clear understanding in what case what handler should be used and in what order they are launched when writing the objects.
Why do we need all these handlers?
Very often the programmer needs to override the default system behavior when writing the objects, notably: cancel writing in case of some conditions; request additional information from the user; refill attributes; write something else to the database based on this record; change something on the form after writing, etc. Every programmer sooner or later faces with the similar problems, so it is necessary for the programmer who works on the 1C 8.2 platform to know a purpose and the launch sequence of these events.
In the form module or in the object module?
Firstly, it is required to decide whether we need these forms? Will the record be written with a software method or only interactively? Well we hold a dialog with the user?
The fact of the matter is that a pert of events is executed at the level of form module and this means that they are executed only on interactive writing, as well as in these events we can address to the form data, hold a dialogue with the user.
Another part of events is executed at the level of object module both on interactive and software writing.
Therefore, it is possible to immediately determine with handler of form module or object module we will work.
Form module: on the client and on the server?
Next, if a form module is chosen, it is necessary to determine what kind of handler we will need: executable on the client or executable on the server. If a dialog with the user will be necessary, then on the client, otherwise, on the server. They can be identified by the name of compilation directive or by the handler name (when on the server, it is written in the name, for example, BeforeWriteAtServer()).
Launch sequence of events (in the order they are listed) and small details:
Many handlers have a parameter «Cancel». If it exists, it means that in this handler it is possible still to cancel writing by setting the parameter “Cancel” a value True, and then the writing will not be performed.
1) Form module BeforeWrite(Cancel, WriteParameters)
Is executed on the client!
This handler should be used if it is required to organize a dialogue with the user before writing an object. Request additional information, notice about something, give an ability to cancel, etc.
The second parameter of this handler “WriteParameters” has a type “Structure”. In the documents these parameters are filled by the system with the predefined parameters “WriteMode”, “PostingMode”. It is possible to add your own.
These parameters are transmitted between the form events “BeforeWriteAtServer”, “OnWriteAtServer”, “AfterWriteAtServer”, where they can be safely used. For example, when writing the information register, it is required to write to another information register an old resource value. It is possible to transmit an old value to these parameters and already in “OnWriteAtServer” to write to another register.
2) Form Module FillCheckProcessingAtServer(Cancel, CheckedAttributes)
3) Object Module FillCheckProcessing (Cancel, CheckedAttributes)
These two handlers for checking the filling are implemented using the parameter “CheckedAttributes” of type Array that contains the attributes to be checked (i.e. for which a filling check property «Throw error» is set).
And if to remove an attribute from this array, it will not be checked, if to add, then a filling will be checked.
Thus, we can say that these two event handles are intended:
- To include in the filling check those attributes for which in the properties “CheckedAttributes” “Do not check” is et. To do this, it is required to add this attribute to array of parameters “CheckedAttributes”.
- In order to exclude from the automatic check the attributes for which a filling check property “Throw error” is set depending on some conditions. To do this, it is required to delete this attribute from array of parameters “CheckedAttributes”.
There are some features that should be taken into account:
- If for the form from which an object is written “AutoFillCheck” is not set in the properties, then these filling check handlers are not called and the checks are not performed!
- Called only on interactive writing! On a software writing they are not called. To check, it is required to user an object method FillCheck() which initializes the launch of these events.
- For the documents that have an ability for conduction these filling check events are called only on conduction!
Both of these events are executed on the server, the difference is that FillCheckProcessingAtServer() is a form module event and, thus, there is an access to the form data. And FillCheckProcessing() is an object module event.
4) Form module BeforeWriteAtServer(Cancel, CurrentObject, WriteParameters)
In this handler it is possible to refill the object attributes or to carry out the additional checks. There is an access to the form data. There is a parameter CurrentObject.
Parameter CurrentObjecthas a type of “object” class depending on the type of written object (CatalogObject, DocumentObject, etc.). That is, an instance of the object is created and it is possible to address its properties and methods, but it is not written in database yet.
5) Object module BeforeWrite(Cancel)
In this handler it is possible to refill the object attributes or to carry out the additional checks.
For the documents two more parameters are added to the parameters of this handler: WriteMode, PostingMode.
6) Object module OnSetNewNumber(StandardProcessing, Prefix)
Occurs at the moment when a number of new object, task or business process is set.
Or OnSetNewCode(StandardProcessing, Prefix) - occurs at the moment when a new number of catalog, exchange plane node or chart of characteristic types is set.
These events are called for the objects for which a property “Auto numeration” is set and only for those objects that have an empty code at the moment of writing.
If to set for the parameter StandardProcessing the value False, a new number will not be generated and it is possible to specify programmatically an object code in this handler.
7) Object module OnWrite(Cancel)
Called after writing an object to the database, but before the end of writing transaction.
A reference already exists and it is possible to write to the database the additional data base on the current object using this reference.
For example, on writing, create another document that contains an attribute – a reference to the written one.
8) Form module WhenRecordingOnServer(Cancel, CurrentObject, WriteParameters)
Called after writing an object to the database, but before the end of writing transaction. Has an access to the form data. There is the last chance to cancel writing.
Parameter CurrentObject has a type of “object” class depending on the type of written object (CatalogObject, DocumentObject, etc.). It is possible to address its properties and methods.
9) Form module AfterWriteAtServer(CurrentObject, WriteParameters)
Executed on the server.
Can be used to visually display something on the form.
10) Form module AfterWrite(WriteParameters)
Executed on the client.
Can be used to visually display something on the form and output a warning to the user.
Example of selecting the event handlers for object writing:
There are the tasks when it is required to use several handlers to solve one task. For example, it is required to request information from the user on writing: «Will we create a new document based on this record?» and if the user will answer in the affirmative, it is required to create a new document with a reference to the created object. And a new document writing must be executed in the transaction, because if the current writing will be canceled for some reasons, the created and written documents should not remain in the database.
To solve this task, it will be required to use the event handlers of form module for two reasons:
1) A dialog with the user is possible only on the client and the client handlers exist only in the form module. For the dialog we will use a client procedure of the form module BeforeWrite() and will save the user answer in the parameter of this procedure “WriteParameters”.
&AtClient Procedure BeforeWrite(Cancel, WriteParameters) If DoQueryBox("Do you want to create a new document?", QuestionDialogMode.YesNo)=DialogReturnCode.Yes Then WriteParameters.Insert("Answer","Yes"); Else WriteParameters.Insert("Answer","No"); EndIf; EndProcedure
2) And in the procedure OnWriteAtServer() of the form module we will get this parameter and, depending on it, we will create a document or not. Why is exactly this procedure? A reference will be received after writing, but since we need to write in transaction, it is required to use the procedures BEFORE the end of transaction, but already having a reference to the written object. BeforeWrite() is not performed, because there is no reference, and AfterWrite() is not performed, because transaction is already completed. OnWrite() remains, but we are faced with a choice: form module or object module? Since an event handler OnWrite() of object module does not contain a parameter that contains the user answer and an event OnWriteAtServer() of form module contains, then the answer is obvious – we use this event OnWriteAtServer() of form module, because:
1) This event is executed in transaction.
2) Contains a parameter “WriteParameters” which already contains the user answer transmitted from the procedure BeforeWrite().
3) A reference is already created and it is possible to create a new document using this reference.
&AtServer Procedure OnWriteAtServer(Cancel, CurrentObject, WriteParameters) If WriteParameters.Answer="Yes" Then DocObject=Documents.Sale.CreateDocument(); DocObject.Date=CurrentDate(); DocObject.DocumentBase= CurrentObject.Ref; //..fill the table and other attributes DocObject.Write(); EndIf; EndProcedure