cancel
Showing results for 
Search instead for 
Did you mean: 

Dynamic input fields in WDA

Former Member
0 Kudos

Hi Folks,

Need to create dynamic input fields based on the [Add] Button click.

The attributes are getting created when I click [Add] button, but i don't see the field on the view screen.

Please let me know what needs to be done for this and what am I missing.

Below is the code that executes on the event of button clicked.

Do I need to write this code in WDDOMODIFYVIEW? if yes then how this will execute with click on the [Add] Button. Thanks.

DATA: lv_count(2) TYPE c.
  DATA: lr_asn_node         TYPE REF TO if_wd_context_node.
  DATA: lr_root_info TYPE REF TO if_wd_context_node_info,
             lr_child_info TYPE REF TO if_wd_context_node_info,
             attr_info TYPE wdr_context_attribute_info,
             le_ip TYPE REF TO cl_wd_input_field.
  DATA: lv_bind_value TYPE string.

  lr_asn_node   = wd_context->get_child_node( name = 'ASN_HDR' ).

  lr_asn_node->get_attribute( EXPORTING name  = 'ADD_COUNT'
                              IMPORTING value = lv_count ).

  lv_count = lv_count + 1.
  lr_asn_node->set_attribute( name  = 'ADD_COUNT'
                              value = lv_count ).

  CONDENSE lv_count.
*** Create Node attribute for PO number

  lr_root_info = wd_context->get_node_info( ).

  CALL METHOD lr_root_info->get_child_node
    EXPORTING
      name            = 'ASN_HDR'
    RECEIVING
      child_node = lr_child_info.

  CONCATENATE 'EBELN' lv_count INTO attr_info-name.
  attr_info-type_name = 'EBELN'.

*** Creates an attribute for the node 'ASN_HDR' of name EBELN concatenated with counter.
  CALL METHOD lr_child_info->add_attribute
    EXPORTING
      attribute_info = attr_info.


  CONCATENATE 'ASN_VIEW.ASN_HDR.' attr_info-name INTO lv_bind_value.

*** Create input field on view ASN_VIEW.  
  CALL METHOD cl_wd_input_field=>new_input_field
    EXPORTING
      bind_value = lv_bind_value
      id         = 'IP'
    RECEIVING
      control    = le_ip.

Accepted Solutions (1)

Accepted Solutions (1)

uday_gubbala2
Active Contributor
0 Kudos

Hi Sandeep,

I am specifying a different approach from Alejandro. This is the methodology that I follow:

1) I have 2 context nodes : NODE & TEST

Am using the attributes under the NODE for binding to the input fields so when the user clicks on the button I would be creating an attribute under this node.

Now coming to the node TEST. I have 2 attributes under this node:

1) CREATE_IP_FIELD of type WDY_BOOLEAN.

2) COUNT of type I with a default value of 0.

Below is my main logic for the program:

When the user clicks on the button I set the value of the boolean attribute CREATE_IP_FIELD to 'X'.

method ONACTIONADD_INPUT_FIELD .
  data: wd_node type ref to if_wd_context_node.
  wd_node = wd_context->get_child_node( name = 'TEST' ).
  wd_node->set_attribute( exporting name  = 'CREATE_IP_FIELD'
                                    value = 'X' ).
endmethod.

Within my WDDOMODIFYVIEW method I first check if the value of CREATE_IP_FIELD is 'X'. If yes then it means that I should:

1) Create a new attribute under node TEST

2) Create a new input field & bind it to the attribute created above

3) Add the new input field to the layout.

The attribute COUNT under the TEST node just contains the current number of input fields on the layout. Its just a number but I would be using this number in my WDDOMODIFYVIEW to determine a unique id creating my input fields & context attributes.

Below is my coding inside the WDDOMODIFYVIEW. It does look a bit complicated but if you go through it keeping in mind the logic i explained above then you should be able to get it.

Regards,

Uday

method WDDOMODIFYVIEW .
  data: lr_node type ref to if_wd_context_node,
        lr_node_info type ref to if_wd_context_node_info,
        lr_attribute_info TYPE wdr_context_attribute_info,
        lv_flag type wd_this->element_test-create_ip_field,
        lr_container type ref to cl_wd_uielement_container,
        lr_inputfield type ref to cl_wd_input_field,
        lv_count type i,
        lv_string1 type string,
        lv_string2 type string.

    lr_container ?= view->get_root_element( ).
    cl_wd_matrix_layout=>new_matrix_layout( container = lr_container ).

    lr_node = wd_context->get_child_node( name = 'TEST' ).
    lr_node->get_attribute( exporting name  = 'CREATE_IP_FIELD'
                            importing value = lv_flag ).
    check lv_flag = 'X'.
"  Since the flag is set we need to create input field & an attribute to bind it to
    lr_node->get_attribute( exporting name  = 'COUNT'
                            importing value = lv_count ).
    lv_count = lv_count + 1.
    move lv_count to lv_string1.
    concatenate 'ATTR'
                lv_string1 into lv_string1.
    condense lv_string1 no-gaps.
    lr_node->set_attribute( exporting name  = 'COUNT'
                                      value = lv_count ).

" Create additional attribute for binding to the input field
    lr_node = wd_context->get_child_node( name = 'NODE' ).
    lr_node_info = lr_node->get_node_info( ).

    lr_attribute_info-name = lv_string1.
    lr_attribute_info-type_name = 'STRING'.
    lr_attribute_info-value_help_mode = '0'.

    lr_node_info->add_attribute( EXPORTING attribute_info = lr_attribute_info ).

" lv_string1 would contain the id to be assigned to our input field
    lv_string1 = lv_count.
    concatenate 'ATTR'
                lv_string1 into lv_string1.
    condense lv_string1 no-gaps.
" lv_string2 would contain the path of the attribute under our node NODE
    concatenate 'NODE.'
                lv_string1 into lv_string2.
    condense lv_string2 no-gaps.

" Creating new input field & binding it to the above created attribute

    lr_inputfield = cl_wd_input_field=>new_input_field( id         = lv_string1
                                                        bind_value = lv_string2 ).
    cl_wd_matrix_head_data=>new_matrix_head_data( element = lr_inputfield ).
    lr_container->add_child( the_child = lr_inputfield ).

"  Reset the CREATE_IP_FIELD flag variable as we finished with creating the input field
    lr_node = wd_context->get_child_node( name = 'TEST' ).
    lr_node->set_attribute( exporting name  = 'CREATE_IP_FIELD'
                                      value = '' ).
endmethod.

Answers (7)

Answers (7)

Former Member
0 Kudos

Thanks Uday, It worked as required, Your help is higly appreciated and rewarded too [:D]

Former Member
0 Kudos

I will try that way

Former Member
0 Kudos

Hello Everyone,

First of all thanks for the replies.

I tried Alejandro methodology but it didn't work out for me,

Uday, your methodology worked for me as required, Special thanks to you.

The only issue what i have now is placing those fields created at the right position, Is that possible? because i have my view where user enters PO numbers and Item number then I have the add button for more PO numbers and Item numbers. after that I have couple of more fields and then the execute button and below there is the tabstrip when the data is fetched and displayed in the table format.

When I click on the [Add] Button the fields are displayed after the Tabular,

I need these input fields just below the [Add] button...is that possible.......

Thanks again

Sandeep

uday_gubbala2
Active Contributor
0 Kudos

Hi Sandeep,

Yes its quite possible to have the input fields which are getting created dynamically to appear right under your push button. You can try proceed as follows:

1) Place a TransparentContainer right under your pushbutton.

2) Now when the user clicks on the pushbutton keep adding the input fields to this TransparentContainer.

3) Just make sure that you remove the stretchedHorizontally & stretchedVertically checkboxes for the ROOTUIELEMENTCONTAINER & your TransparentContainer.

In my earlier code I have given you the logic to add the InputFields to the ROOTUIELEMENTCONTAINER because of this they would be getting added at the end of your layout. So you would have to make a small change in this.

In the beginning of our code in WDDOMODIFYVIEW we had written as:

lr_container ?= view->get_root_element( ).
  cl_wd_matrix_layout=>new_matrix_layout( container = lr_container ).

Here we were fetching the reference of the ROOTUIELEMENTCONTAINER & then using it later in our program for adding our input fields to it by saying as:

lr_container->add_child( the_child = lr_inputfield ).

So now you would just have to get the reference of your TransparentContainer into lr_container & the rest of the program would remain the same. Suppose you have a TransparentContainer with id TC1 in your view then you can do it as follows:

lr_container ?= view->get_element( id = 'TC1' ).
  cl_wd_matrix_layout=>new_matrix_layout( container = lr_container ).

Regards,

Uday

alejandro_bindi
Active Contributor
0 Kudos

Well I just wanted to say that if it didn't work it must be something missing on your part.

My coding wasn't complete or activated on a system (it was missing parts such as layout data for the inputfield), it was just an idea for you to implement it.

Actually, the main difference I see between my suggestion and Uday's is that I'm passing data using controller attributes (not the context). As a general rule, if you need to save something which is not necessary to be shown on screen (like the counters or field names in this case), you shouldn't store them in the context, but as controller attributes. Both because A) it is faster, and B) it is more easily accessed (you don't need to use methods to set and get data, such as node->set_attribute and get_attribute).

Anyway, the solution you used is still perfectly valid.

Regards

Former Member
0 Kudos

hi,

for creation of dynamic fields you have to use wddomodify() in the view.for every action performed on the view , code in wddomodify() gets executed ,so your code gets executed whenever you click on the button.

Former Member
0 Kudos

Hi,

You can also write code in wdDoInit () but only thing is that you need to instanisiate the view.

ie. DATA: myView type ref to if_wd_view.

Then you can write dynamic coding for input fields

Best Regards

Ravi

uday_gubbala2
Active Contributor
0 Kudos

Hi,

Sandeep dont heed attention to what Ravi was saying. Its absolutely wrong. You are not supposed to write any dynamic coding within any method other than the WDDOMODIFYVIEW. And Ravi what do you mean by instantiating the if_wd_view? In order to work with your layout you need a reference to your components view & the only place where you can get this reference is within the WDDOMODIFYVIEW method. You can't just create any instance and start working with it from WDDOINIT.

Regards,

Uday

former_member402443
Contributor
0 Kudos

Hi,

Please go thru the links below for dynamic programming for creation of group.

[Dynamic prog. Part 1|https://www.sdn.sap.com/irj/scn/weblogs?blog=/pub/wlg/2888] [original link is broken] [original link is broken] [original link is broken];

[Dynamic Prog. Part 2|https://www.sdn.sap.com/irj/scn/weblogs?blog=/pub/wlg/2915] [original link is broken] [original link is broken] [original link is broken];

[dynamic prog part 3|https://www.sdn.sap.com/irj/scn/weblogs?blog=/pub/wlg/2953] [original link is broken] [original link is broken] [original link is broken];

Regard

Manoj Kumar

alejandro_bindi
Active Contributor
0 Kudos

That's right, only inside WDDOMODIFYVIEW you can generate UI elements such as inputfields in your case.

What you can do, since MODIFYVIEW will execute after your event handler (and after any action, for that matter), is something like this:

1) Create a view controller attribute table, e.g. NEW_FIELDS[], with the following definition:

ID

BIND_VALUE

2) Populate this table in your ONACTIONADD event handler:

Instead of this code:


CONCATENATE 'ASN_VIEW.ASN_HDR.' attr_info-name INTO lv_bind_value.

*** Create input field on view ASN_VIEW.  
  CALL METHOD cl_wd_input_field=>new_input_field
    EXPORTING
      bind_value = lv_bind_value
      id         = 'IP'
    RECEIVING
      control    = le_ip.

use this:


DATA ls_new_field LIKE LINE OF WD_THIS->NEW_FIELDS.

CONCATENATE 'IP' lv_count INTO ls_new_field-id. "UI elem. ID must be unique on the view
CONCATENATE 'ASN_VIEW.ASN_HDR.' attr_info-name INTO ls_new_field-bind_value.

APPEND ls_new_field TO WD_THIS->NEW_FIELDS

3) Use WDDOMODIFYVIEW like this:


DATA ls_new_field LIKE LINE OF WD_THIS->NEW_FIELDS.
IF WD_THIS->NEW_FIELDS IS NOT INITIAL.
  LOOP AT WD_THIS->NEW_FIELDS INTO ls_new_field.
    CALL METHOD cl_wd_input_field=>new_input_field
      EXPORTING
        bind_value = ls_new_field-bind_value
        id         = ls_new_field-id
      RECEIVING
        control    = le_ip.

*    finish adding the inputfield to the view
     ...

  ENDLOOP.
* clear the table so they won't be recreated on the next roundtrip
  REFRESH WD_THIS->NEW_FIELDS.
ENDIF.

(actually, you could use a simple structure instead of a table, but this allows to create more than one field in one step, should you need that in the future)

Here you have examples of ViewElements creation at runtime, inside WDDOMODIFYVIEW:

/people/thomas.szcs/blog/2006/01/03/dynamic-programming-in-web-dynpro-abap--part-ii-handling-viewelements

Hope you get the idea.

Regards

Edited by: Alejandro Bindi on Mar 4, 2009 7:50 AM

Fixed error (REFRESH location)