• Home   /  
  • Archive by category "1"

Custom Assignment Block

Block definitions describe how a block looks and behaves, including the text, the colour, the shape, and what other blocks it can connect to.

Once the custom blocks are defined, each platform loads these definitions in different ways, detailed in web and Android specific configuration guides.

Note: Most of a block can be defined using the Blockly Developer Tools, instead of manually creating the code below.

JSON format versus JavaScript API

Blockly has two ways of defining blocks. The JSON format is cross-platform so that the same code may be used to define blocks on web, Android, and iOS. Additionally, the JSON format is designed to simplify the internationalization process when developing for languages with different word orderings. The JSON format is the preferred method of defining blocks.

However, the JSON format is not able to define advanced features such as mutators or validators. Blocks on the web using these more complicated features need to be defined using the JavaScript API. Separate APIs are being developed for other platforms but are not currently available.



The function creates the block's shape. In the context of this function the keyword is the actual block being created.

Both examples load the same 'string_length' block.

On the web, the JSON format is loaded using the function. This also allows mixing the two formats in Blockly webpages. It is preferred to define your block with JSON wherever possible, and use JavaScript only for parts of block definitions that JSON does not support.

Below is an example of a block that is predominantly defined using JSON, but is extended using the JavaScript API to feature a dynamic tooltip.


Block colour



Blockly uses a Hue-Saturation-Value (HSV) colour model. Saturation and Value are hard-coded into Blockly, whereas the Hue is defined on each block. This ensures that developers have the freedom to choose from a wide range of colours, while still guaranteeing that all the blocks will fit together visually. It also allows the entire Blockly look and feel to be made brighter (for children) or more depressing (for businesses) by simply adjusting the two hard-coded Saturation and Value constants.

To find a good colour, visit this HSV picker, enter Blockly's Saturation and Value constants (the defaults are 45% and 65% respectively), then slide the Hue as desired. Use this Hue value as the argument to the function. Note the British spelling. Failure to set the colour results in a black block.

Statement Connections

Users can create sequences of blocks using the and connectors. In Blockly's standard layout, these connections are on the top and the bottom, with the blocks stacked vertically.

A block with a previous connector cannot have an output connector, and vice versa. The term statement block refers to a block with no value output. A statement block will usually have both a previous connection and a next connection.

and connections can be typed, but this feature is not utilized by standard blocks.

Next Connection

Creates a point at the bottom of the block, so that other statements can be stacked below it. A block with a next connection but no previous connection usually represents an event, and can be configured to render with a hat.



Typed (rare):



Typed (rare):

Previous Connection

Creates a notch at the top of the block, so that it can be connected as a stack of statements.

Blocks with a previous connection cannot have an output connection.



Typed (rare):



Typed (rare):

Block Output

A block may have a single output, represented as a male jigsaw connector on the leading edge. Outputs connect to value inputs. Blocks with an output are usually called value blocks.







Blocks with an output connector cannot also have a previous statement notch.

Block Inputs

A block has one or more inputs, where each input is a sequence of labels and fields that may end in a connection. There are three types of inputs, matching the connection types:

  • Value input: Connects to a output connection of a value block. A block (addition, subtraction) is an example of a block with two value inputs.
  • Statement input: Connects to a previous connection of a statement block. The nested section of a while loop is an example of a statement input.
  • Dummy input: Does not have a block connection. Acts like a newline when the block is configured to use external value inputs.

The JSON format and JavaScript API use slightly different models to describe their inputs.

Inputs and Fields in JSON

JSON defined blocks are structured as a sequence of interpolated message strings ( , , ...), where each interpolation token (, , ...) is a field or an input end (thus where the input connector renders, within the message) in the matching JSON array. This format is intended to make internationalization easy.


The interpolation tokens must match the array completely: no duplicates, no omissions. Tokens may be present in any order, which allows different languages to change the layout of the block.

Text on either side of an interpolation token is whitespace-trimmed. Text using the character (e.g. when referring to a percentage) should use so that it is not interpreted as an interpolation token.

The order of the arguments and the argument types define the shape of the block. Changing one of these strings can completely change the block's layout. This is particularly important in languages that have a different word order than English. Consider a hypothetical language where (as used in the example above) needs to be reversed to say . Changing this one string (and leaving the rest of the JSON untouched) results in the following block:

Blockly automatically changed the order of the fields, created a dummy input, and switched from external to internal inputs.


Each message string is paired with an array of the same number. For example, goes with . The interpolation tokens (, , ...) refer to the items of the array. Every object has a string. The rest of the parameters vary depending on the type:

Every object may also have an field. In the case that Blockly does not recognize the object's , then the object is used in its place. For example, if a new field named is added to Blockly, blocks using this field could use to define a fallback for older versions of Blockly:


An object may have its own object, thus allowing for chaining. Ultimately, if Blockly cannot create an object in the array (after attempting any objects) then that object is simply skipped.

A dummy input will be automatically added to the end of the block if the string ends with text or fields that are not contained by an input. Thus if the last input on a block is a dummy input then it may be omitted from the array and it does not need interpolation into . The automatic addition of a tailing dummy input allows translators to change without needing to modify the rest of the JSON. See the example of (no dummy input) and (dummy input added) earlier on this page.

In rare cases the automatically created trailing dummy input needs to be aligned to the or . The default if not specified is .

In the example below is and Blockly automatically adds a dummy input for the third row. Setting to forces this row to be right aligned.

When designing blocks for RTL (Arabic and Hebrew), left and right are reversed. Thus would align fields to the left.

, ,

Some blocks are naturally divided into two or more separate parts. Consider this repeat block which has two rows:

If this block were described with a single message, the property would be . This string is awkward for a translator, it is difficult to explain what the substitution means. The dummy input may also not even be desired in some languages. And there may be multiple blocks that wish to share the text of the second row. A better approach is for JSON to use more than one message and args properties:


Any number of , , and properties may be defined in the JSON format, starting with 0 and incrementing sequentially. Note that the Block Factory is not capable of splitting messages into multiple parts, but doing so manually is straightforward.

Inputs and Fields in JavaScript

The JavaScript API includes an method for each input type:


Each method can take an identifier string, used by code generators. Dummy inputs rarely need referencing and the identifier is usually left unset.

As seen above, each method returns the input object for configuration through method chaining. There are three functions that are used for configuring inputs.


This optional function is used for type-checking of connected inputs. If given an argument of null, the default, then this input may be connected to any block. See Type Checks for details.


This optional function is used to align the fields (see below). There are three self-descriptive values which may be passed as an argument to this function: , , and . Note the British spelling of 'centre'. Left alignment is the default.

When designing blocks for RTL (Arabic and Hebrew), left and right are reversed. Thus would align fields to the left.

Once an input has been created and appended to a block with , one may optionally append any number of fields to the input. These fields are often used as labels to describe what each input is for.


The simplest field element is text. Blockly's convention is to use all lowercase text, with the exception of proper names (e.g. Google, SQL).

An input row can contain any number of field elements. Multiple calls may be chained together to efficiently add several fields to the same input row.


The call is actually a shortcut for using an explicit FieldLabel constructor: . The only time one would wish to use the constructor is when specifying a class name so that the text may be styled using a CSS rule.

Inline vs. External

Block inputs can render as either external or internal.

The block definition can specify an optional boolean controlling whether inputs are inline or not. If then any value inputs will be external (such as the left block). If then any value inputs will be inline (such as the right block above).



If not defined then Blockly will use some heuristics to guess which mode is best. Assuming Blockly makes the right choice, leaving this field undefined is preferable since different language translations can automatically have different modes. See the JSON example of (external inputs) and (inline inputs) earlier on this page.

Use inline inputs when a block is likely to have small inputs such as numbers. The user can toggle this option through the context menu, if the configuration is enabled (defaults to true if the toolbox has categories).


Fields define the UI elements within a block. These include the string labels, images, and inputs for literal data such as strings and numbers. The simplest example is the block, either a (web) or (Android) to type a number.

Most fields have a name string used to reference them during code generation.


Label strings provide context to the other fields and inputs. They are so common and intrinsic to translation, they have their own notation.


Any message text between interpolation arguments becomes label strings. Alternatively, labels may be interpolated explicitly, either as an object or as text.


accepts both and, more commonly, strings to create labels.

When added explicitly, authors can include a CSS style name to customize the view on Blockly for Web.




Like labels, images are usually static indicators instead of input fields.



The object is created with the image URL and the desired height and width. The image will be scaled to within the specified dimensions, while preserving the aspect ratio. The block will expand as needed to accommodate the image. An optional fourth argument specifies the alternate text for use when the block is collapsed.

The image URL can be relative. On web, relative URLs are resolved relative to hosting page's URL. On Android, the relative URL is treated as an asset path. On iOS, a relative URL must be a simple file name (no path) and will be resolved as a file in the application bundle.

Text Field

Text input allows the user to input text.



Optionally, the JavaScript constructor can also take a second argument which becomes the validation function or change handler. See for an example of where the user's input is rewritten.

By default, text input input is spell checked, but can be optionally turned off:



Drop-down Field



The items list of the drop-down field is specified by a list of two-part lists. The first item of each inner list is the human readable name; the second is the item identifier string.

In Blockly for Web, if all of the human readable strings share the some prefix or suffix, those strings will extracted as a label before or after the drop down. This allows the prefix/suffix label place to adapt to language conventions. This feature will be ported to Android in the near future.

Note: See Drop-Down Menus for more info.

Checkbox Field

A checkbox field provides a boolean input.



Optionally, the constructor can also take a second argument which becomes the validation function or change handler.

Colour Picker Field

The colour picker allows the user to select from a set of opaque colours provided by the programmer.

Note: All JavaScript and JSON Blockly APIs use the British 'colour' spelling. Android APIs use the US spelling to conform with the Android platform.



Optionally, the JavaScript constructor can also take a second argument which becomes the validation function or change handler.

In web Blockly, the selection of colours and number of columns displayed in all colour pickers can be set globally:


Alternatively, an individial colour picker can be given a custom selection:


Use any CSS-compatible format for the list of colours, including , , or .

Variable Field

Another field element is a variable selection menu. The field defines the default variable name to use (in this case ). If this name is omitted, the variable will be a new unique variable (e.g. , , ...).



Number Field

Number fields provide number input and validation. In mobile environments, unlike normal text inputs, this can bring up a number pad for the on-screen keyboard.

Caution: Number fields are in development. While Android and generators properly support number fields, the web UI is not yet implemented.



Using additional parameters, numeric input can be constrained in a number of ways. The range can be constrained by and values. Setting (usually a power of 10) enforces a minimum step between values. That is, the user's value will rounded to the closest multiple of . The least significant digit place is inferred from the . Integers values can be enforces by choosing an integer precision.



Some combinations of constraints are invalid, and should be avoided. For example, a range of 1 to 4 with a precision of 5 has no valid values.

Optionally, the JavaScript constructor can also take a fifth argument which becomes the validation function or change handler.

Angle Field

Angle fields present a UI to graphically select an angle.

By default, this is from 0° (inclusive) to 360° (exclusive) counter-clockwise, with 0° to the right, and 90° to the top. Out of bound values are wrapped onto this scale. Any angle (even fractional) can be entered with the keyboard, but angles selected with the mouse are rounded to 15°.



In the last Blog i showed how can you create your own custom BOL object that meet your personal requirements .

Now that we have our BOL Object we might want to use it for our purposes.

Let's say that we want to add several fileds to assignment block and display them on the screen ,for instance we take the fields from our Z table the we use in the creation of our BOL Object .

we also want to keep the connection for the original transaction context .

the steps for doing that are :

1) we need to add a filed to our Z table BP_GUID which will keep us connected to the main transaction context .

2) perform the adjustment for the Z Table

3) Search for the right BP_GUID that fit to our user account .

4) create new record that contain the details that we want to diasply for the spesific account

See the following screen shot.

 Here we should add the BP_GUID feild to our table and mark the field as a part of the table key .

See the following screen shot

Now we need to perform some adjustment for our table . choose the Database Utility from the menu
See the following screen shot

once you choose this option you'll get the next screen .

In our case we will choose the Delete data option becuse we want to create a new record, you also have to know that if you choose the Save data option there's no 100  percent guarantee that your data in the table will be saved , so you should consider the use of Database Utility very careful. 

After we perform the adjustment and activated the table we can step forward to the next step which is the creation of a new record with the details that we want to display on the screen . 

First to the record creation we should find the key which is the BP_GUID that will connect us to the account context . 

 to find the right BP_GUID enter transaction GENIL_BOL_BROWSER and insert the BP_APPL_COND  in the component set field.

See the following screen shot

when you enter to the component set choose the predefined search named BuilEmpSearch  

 See the following screen shot.

Now we can look for any partner , in my case i'll choose to search  my user and i'll get the compatible

BP_GUID which is : DF21EBC73A26F8F1A2B0001F29644FC0
See the following screen shot.

 Now let's create a new record in the DataBase table ZUSR_BOL_TB with user name, BP_GUID , First and last names.
See the following screen shot.

for now we finish with the database side and we wiil go to perform some improvement in our BOL object to support the different searching options.

so let's go to transaction SE24 and put ZCL_OWN_BOL in the input filed.
click on Local Types button and put the lines inside :

TYPES: BEGIN OF ty_general_rng ,
                sign TYPE bapisign,
                option TYPE bapioption,
                low TYPE string ,
               high TYPE string ,
END OF ty_general_rng .

TYPES: tt_general_rng TYPE STANDARD TABLE OF ty_general_rng . 
See the following screen shot:

Now go back to the method list and edit the method :IF_GENIL_APPL_INTLAY~GET_DYNAMIC_QUERY_RESULT
replace the exsiting code with the bellow lines:
METHOD if_genil_appl_intlay~get_dynamic_query_result.

DATA: lr_object TYPE REF TO if_genil_cont_root_object,
            lt_result TYPE TABLE OF zusr_bol_st,
            lv_dyn_where TYPE string,
            lv_len TYPE i ,
            ls_range TYPE ty_general_rng.

DATA: lt_bp_guid TYPE tt_general_rng,
            lt_bname_range TYPE tt_general_rng,
           lt_name_first TYPE tt_general_rng,
           lt_name_last TYPE tt_general_rng.


We might want to add the BNAME ,NAME_LAST,NAME_FIRST fileds to a view that we will create

personaly i choosed the BP_HEAD component but you can choose any component that you may use .

 OK. So let's get in and execute transaction BSP_WD_CMPWB_NEW and choose BP_HEAD component with our enhancement set which is spesificaly in my case called ZENH_CRM and hit the  display button and go to Runtime Repository Editor , open the MODELS folder to see with which BOL component set the BP_HEAD component use.

See the following screen shot.

we can see now that the component BP_HEAD use the Model BP_APPL_COND and we want that our BOL object will appear in the repository of the BP_HEAD component so that we can use it for our pupose.

To do that we need to go to the component set definition .

See the following screen shot.

now choose the appropriate component set which is in our case BP_APPL_COND.

See the following screen shot.

now click on component assignment make new entry and add our BOL object named ZBOLOB.

See the following screen shot.

don't forget to save the new entry .

after you saved it successfully enter again to BSP_WD_CMPWB_NEW transaction with BP_HEAD component and click on the BOL Model Browser tab , we want to check here that we can see our BOL entity ready for use .

See the following screen shot.

Now we can see that our BOL entity Root that we created is ready for use in the enhancement of BP_HEAD component.  We will go to Component Structure Browser tab and create our view .

See the following screen shot.

we'l choose a name for our view .
See the following screen shot.

 after we named the view we need to add 2 model nodes , one for BuilHeader and one
 for our Root BOL object .
 The first one is for getting the relevant BP_GUID from the custom controller and get the appropriate
 first name last name and user name accroding to our table .

 See the following screen shot.

The next step is to add the fields that we might use in our view to context which we working on .

we start with the BuilHeader fields .

See the following screen shot.

we use also attributes from the Root BOL object .

See the following screen shot.

we got the whole attributes as shown bellow.

See the following screen shot.

we move to the nest step .

here we need to define the view type and it's properties.

the view type we choose form view without buttons and in the properties we make it configurable 

and that for keep to our self the option to Add/Remove attributes from the view .

See the following screen shot.

Now we finish the view addtion with the wizard we will see that our view is listed with

the other views in the component.

See the following screen shot.

After we added the view we should create a binding to the custom controiller context node BUILHEADER.

so we put the mouse curser on the context node BUILHEADER pressing teh right mouse

click and create the binding .

See the following screen shot.

we will create the binding for our context node to the same context node in the custom controller.

See the following screen shot.

After we create the apropriate binding we need to add the attributes to the view .

so we move to the configuration tab when we working on the view and the we switch to edit mode .

we see that we have the 2 BOL objects that we added when we wroking with the wizard in time of the view creation .

in our case we will add the attributes from the Root BOL object .

See the following screen shot.

After we add the attributes to our view we need to add our view as an assignment block .

First we need to add our view to the BPHEADOverview viewset , to do this we will go to the

Runtime Repository Editor and we will add our view to the OverviewPage of

BPHEADOverview viewset .

See the following screen shot.

After we add the view to the BPHEADOverview viewset we will go to the configuration tab of

BPHEADOverview viewset and switch to edit mode and add our view TestBOLroot to the list of views

that appears as assignment blocks in the BPHEADOverview viewset by click on the arrow button

and moving it from the left side to the right side .

See the following screen shot.

After we handle the addition of adding our view as an assignment block we need to handle some code

addtions for the right treatment in the attributes in our view .

First we will go to the ROOT context node within our view and redefine

the method IF_BSP_MODEL~INIT.

See the following screen shot.

Put the next ilnes into the method save and aactivate the method.



TYPES: BEGIN OF ltype_attr_struct,

                       mandt TYPE mandt,

                       bp_guid TYPE bu_partner_guid,

                       bname TYPE xubname,

                      name_last TYPE bu_namep_l,

                      name_first TYPE bu_namep_f,

END OF ltype_attr_struct.

DATA: lrf_data_struct TYPE REF TO ltype_attr_struct,

           lrf_value_node TYPE REF TO cl_bsp_wd_value_node,

           lrf_bol_collection TYPE REF TO if_bol_bo_col.

super->if_bsp_model~init( id = id owner = owner ).

CREATE DATA lrf_data_struct.

CREATE OBJECT lrf_value_node


          iv_data_ref = lrf_data_struct.

CREATE OBJECT lrf_bol_collection TYPE cl_crm_bol_bo_col.

 lrf_bol_collection->add( lrf_value_node ).

 me->set_collection( lrf_bol_collection ).



After we add the above lines to the method we will go to the implementation class of our view,

which is in our case is ZL_ZBP_HEAD_TESTBOLROOT_IMPL.

we will double click on the class name and we will move to display mode of the class in a way that

all the method could be shown. 

The first thing to do is to write our own method for performing the right query when we need to

display the attributes on the screen .

After that we will redefine the method DO_PREPARE_OUTPUT.

so let's create a new method named root_query which is an Instance Method , and the visibility of

it is Private.

put the next lines to the method .


METHOD root_query.

DATA: lrf_advanced_query TYPE REF TO cl_crm_bol_dquery_service,

           lrf_root_result_collection TYPE REF TO if_bol_entity_col,

           lrf_root_result_bol_entity TYPE REF TO cl_crm_bol_entity,

           lrf_current_root TYPE REF TO if_bol_bo_property_access,

           lrf_current_builheader TYPE REF TO if_bol_bo_property_access,

           lt_params TYPE crmt_name_value_pair_tab,

           ls_params TYPE crmt_name_value_pair,

           ls_builheader_properties TYPE crmst_header_object_buil,

           lv_low_value TYPE string ,

           ls_root_properties TYPE zusr_bol_st.

ls_params-name = 'MAX_HITS' .

ls_params-value = '1'. "we don't need in this case more the single record for result

APPEND ls_params TO lt_params.

lrf_current_root ?= me->typed_context->root->collection_wrapper->get_current( ).

CHECK lrf_current_root IS BOUND .

lrf_current_root->get_properties( IMPORTING es_attributes = ls_root_properties ).

CHECK ls_root_properties IS INITIAL . " means that we don't have any values in our

                                                                 "fields and  therfore wi'll excute the query

lrf_current_builheader ?=

  me->typed_context->builheader->collection_wrapper->get_current( ).

CHECK lrf_current_builheader IS BOUND .

lrf_current_builheader->get_properties( IMPORTING es_attributes = ls_builheader_properties ).

CHECK ls_builheader_properties-bp_guid IS NOT INITIAL .

lv_low_value = ls_builheader_properties-bp_guid.

lrf_advanced_query = cl_crm_bol_dquery_service=>get_instance( 'Search' ).

lrf_advanced_query->set_query_parameters( it_parameters = lt_params ).

lrf_advanced_query->add_selection_param( iv_attr_name = 'BP_GUID'

                                                                iv_sign = 'I'

                                                                iv_option = 'EQ'

                                                                iv_low = lv_low_value

                                                                iv_high = '' ).

lrf_root_result_collection = lrf_advanced_query->get_query_result( ).

IF lrf_root_result_collection IS BOUND . "if we found something that match our selection

lrf_root_result_bol_entity = lrf_root_result_collection->get_first( ).

lrf_root_result_bol_entity->get_properties( IMPORTING es_attributes = ls_root_properties ).

lrf_current_root->set_properties( is_attributes = ls_root_properties ).




Save and activate your code .

the next step is to redefine the method DO_PREPARE_OUTPUT.

put the next lines into the method .





                  iv_first_time = iv_first_time.

me->ROOT_QUERY( ).



save and activate your code .

Now all job is done our BOL object is wroking like a Rolls-Royce and it's time to derive pleasure from .

We will go to the webclient , choose our account and display it .

we can see that we have our attributes shown on the screen .

See the following screen shot.

One thought on “Custom Assignment Block

Leave a comment

L'indirizzo email non verrĂ  pubblicato. I campi obbligatori sono contrassegnati *