在上一文中,介绍了动态控制字段属性的两个方法,在这里主要介绍在BOPF中的实现。这里动态控制,主要为控制字段的只读(R),可编辑(C),隐藏(H),强制输入(M),
1.CDS添加注释
要在BOPF的CDS,或者最终显示 的CDS中为每个一个需要控制的字段添加自定义控制注释,如下:
1 2 3 4 |
// @ObjectModel.mandatory: 'EXTERNAL_CALCULATION' @ObjectModel.readOnly: 'EXTERNAL_CALCULATION' // @ObjectModel.enabled: 'EXTERNAL_CALCULATION' Yhzh, |
如上面的代码为YHZH字段增加了可控制注释。其中的mandatory,readOnly,enabled,在实际使用中发现,只要定义一行就可以了,暂时未发现异常。
2.BOPF添加Determinations
我的是有草稿的BOPF,自动生成了一个名为ACTION_AND_FIELD_CONTROL的Determination,如不是草稿的,或者没有此Determination,可手动添加一下,来定入代码。

在类方法ZCL_D_TRD_I_ACC_APPLY_ACTION_1->/BOBF/IF_FRW_DETERMINATION~EXECUTE中写入代码调用方法SET_FIELD_CTRL,此方法是自定义的一个方法,可查看此类方法。控制字段的必输入性,也可以在此直接写入SET_FIELD_CTRL方法的的控制,
在代码中,我从自定义表ZTRT_BOPF_FUCT_F中取出要控制字段的配置属性,然后分别按只读(R),可编辑(C),隐藏(H),强制输入(M)来进行字段控制。

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 |
METHOD /BOBF/IF_FRW_DETERMINATION~EXECUTE. * BREAK YANGSEN. DATA: LT_ACTIVE_ACCOUNT TYPE ZTTRD_I_ACC_APPLY, LT_DRAFT_ACCOUNT TYPE ZTTRD_I_ACC_APPLY, LS_DRAFT_ACCOUNT TYPE ZSTRD_I_ACC_APPLY, LT_ACCOUNT TYPE ZTTRD_I_ACC_APPLY, LS_ACCOUNT TYPE ZSTRD_I_ACC_APPLY, LV_UI_STATUS TYPE CHAR2, "1 for create, 2 for edit, 3 for display LV_UI_STATUS_EXT TYPE CHAR2, "1 for create, 2 for edit, 3 for display LV_ACCOUNT_ACTION TYPE ZTR_FUN_OPERATION, "01:Open, 02:Modify, 03:Close, 07:Reopen, 08:Modify and Reopen LV_PROCESS_ACTION_CTRL TYPE ABAP_BOOL, LV_PROCESS_FIELD_CTRL TYPE ABAP_BOOL, LV_ENABLE_EDIT TYPE ABAP_BOOL, LV_ENABLE_COPY TYPE ABAP_BOOL, LV_ENABLE_DELETE TYPE ABAP_BOOL, LV_ENABLE_APPROVAL TYPE ABAP_BOOL, LV_ENABLE_FIOK TYPE ABAP_BOOL. DATA(LO_SET_PROPERTY) = NEW /BOBF/CL_LIB_H_SET_PROPERTY( IS_CONTEXT = IS_CTX IO_MODIFY = IO_MODIFY ). LV_PROCESS_ACTION_CTRL = ABAP_FALSE. READ TABLE IS_CTX-FILTERED_ATTRIBUTES WITH KEY TABLE_LINE = 'ACTION' INTO DATA(LV_ATTR). " #NO_TEXT IF SY-SUBRC = 0. LV_PROCESS_ACTION_CTRL = ABAP_TRUE. ENDIF. LV_PROCESS_FIELD_CTRL = ABAP_FALSE. READ TABLE IS_CTX-FILTERED_ATTRIBUTES WITH KEY TABLE_LINE = 'ALL_NODE_PROPERTY' INTO LV_ATTR. " #NO_TEXT IF SY-SUBRC = 0. LV_PROCESS_FIELD_CTRL = ABAP_TRUE. ENDIF. * SEPARATE INTO ACTIVE AND DRAFT KEYS DATA(LO_DRAFT_ACTIVE) = /BOBF/CL_LIB_DRAFT_ACTIVE=>GET_INSTANCE( IV_BO_KEY = IS_CTX-BO_KEY ). CALL METHOD LO_DRAFT_ACTIVE->SEPARATE_KEYS EXPORTING IV_NODE_KEY = IS_CTX-NODE_KEY IT_KEY = IT_KEY IMPORTING ET_DRAFT_KEY = DATA(LT_DRAFT_BOPF_KEYS) ET_ACTIVE_KEY = DATA(LT_ACTIVE_BOPF_KEYS). DESCRIBE TABLE LT_DRAFT_BOPF_KEYS LINES DATA(LV_LINES_DRAFT_KEYS). DESCRIBE TABLE LT_ACTIVE_BOPF_KEYS LINES DATA(LV_LINES_ACTIVE_KEYS). *--------------------------------------------------------------------* *--------------------------------------------------------------------* * DATA RETRIEVE *--------------------------------------------------------------------* "ACTIVE DATA "ACTIVE DATA TEST-SEAM MOCK_ACCOUNT. * IF LV_LINES_ACTIVE_KEYS EQ 1. IO_READ->RETRIEVE( EXPORTING IV_NODE = IS_CTX-NODE_KEY IT_KEY = LT_ACTIVE_BOPF_KEYS IV_FILL_DATA = ABAP_TRUE * IT_REQUESTED_ATTRIBUTES = LT_REQ_ATTR IMPORTING EO_MESSAGE = EO_MESSAGE ET_DATA = LT_ACTIVE_ACCOUNT ET_FAILED_KEY = ET_FAILED_KEY ). IF NOT ET_FAILED_KEY IS INITIAL. ASSERT 1 = 2. RETURN. ENDIF. * ENDIF. "DRAFT DATA * IF LV_LINES_DRAFT_KEYS EQ 1. IO_READ->RETRIEVE( EXPORTING IV_NODE = IS_CTX-NODE_KEY IT_KEY = LT_DRAFT_BOPF_KEYS IV_FILL_DATA = ABAP_TRUE * IT_REQUESTED_ATTRIBUTES = LT_REQ_ATTR IMPORTING EO_MESSAGE = EO_MESSAGE ET_DATA = LT_DRAFT_ACCOUNT ET_FAILED_KEY = ET_FAILED_KEY ). IF NOT ET_FAILED_KEY IS INITIAL. ASSERT 1 = 2. RETURN. ENDIF. * ENDIF. END-TEST-SEAM. *--------------------------------------------------------------------* *--------------------------------------------------------------------* * LIST PAGE *--------------------------------------------------------------------* IF LV_LINES_ACTIVE_KEYS + LV_LINES_DRAFT_KEYS GT 1. * HANDLE ACTIVE KEYS LOOP AT LT_ACTIVE_ACCOUNT ASSIGNING FIELD-SYMBOL(<LS_ACTIVE_ACCOUNT>). DETERMINE_ACTION_BUTTEN( EXPORTING IS_CTX = IS_CTX IT_KEY = IT_KEY IO_READ = IO_READ IO_MODIFY = IO_MODIFY IV_ACCOUNT = <LS_ACTIVE_ACCOUNT> IS_DRAFT = '' IMPORTING EO_MESSAGE = EO_MESSAGE ET_FAILED_KEY = ET_FAILED_KEY ). ENDLOOP. * HANDLE DRAFT KEYS LOOP AT LT_DRAFT_ACCOUNT ASSIGNING <LS_ACTIVE_ACCOUNT> . DETERMINE_ACTION_BUTTEN( EXPORTING IS_CTX = IS_CTX IT_KEY = IT_KEY IO_READ = IO_READ IO_MODIFY = IO_MODIFY IV_ACCOUNT = <LS_ACTIVE_ACCOUNT> IS_DRAFT = 'X' IMPORTING EO_MESSAGE = EO_MESSAGE ET_FAILED_KEY = ET_FAILED_KEY ). ENDLOOP. RETURN. ENDIF. *--------------------------------------------------------------------* *--------------------------------------------------------------------* * OBJECT PAGE *--------------------------------------------------------------------* * ACTION CONTROL *--------------------------------------------------------------------* IF LV_PROCESS_ACTION_CTRL = ABAP_TRUE. * HANDLE DRAFT KEYS LOOP AT LT_DRAFT_BOPF_KEYS ASSIGNING FIELD-SYMBOL(<LS_DRAFT_KEY>) . * DISABLE 自定义按钮 LO_SET_PROPERTY->SET_ACTION_ENABLED( IV_ACTION_KEY = ZIF_TRD_I_ACC_APPLY1_C=>SC_ACTION-ZTRD_I_ACC_APPLY-SET_ACCNO_APPROVAL IV_KEY = <LS_DRAFT_KEY>-KEY IV_VALUE = ABAP_FALSE ). LO_SET_PROPERTY->SET_ACTION_ENABLED( IV_ACTION_KEY = ZIF_TRD_I_ACC_APPLY1_C=>SC_ACTION-ZTRD_I_ACC_APPLY-SET_ACCNO_FIOK IV_KEY = <LS_DRAFT_KEY>-KEY IV_VALUE = ABAP_FALSE ). ENDLOOP. ENDIF. * HANDLE ACTIVE KEYS LOOP AT LT_ACTIVE_ACCOUNT ASSIGNING <LS_ACTIVE_ACCOUNT> . DETERMINE_ACTION_BUTTEN( EXPORTING IS_CTX = IS_CTX IT_KEY = IT_KEY IO_READ = IO_READ IO_MODIFY = IO_MODIFY IV_ACCOUNT = <LS_ACTIVE_ACCOUNT> IMPORTING EO_MESSAGE = EO_MESSAGE ET_FAILED_KEY = ET_FAILED_KEY ). ENDLOOP. *--------------------------------------------------------------------* * Field Control *--------------------------------------------------------------------* IF LV_PROCESS_FIELD_CTRL = ABAP_TRUE. IF LV_LINES_ACTIVE_KEYS EQ 1. MOVE-CORRESPONDING LT_ACTIVE_ACCOUNT TO LT_ACCOUNT. ELSEIF LV_LINES_DRAFT_KEYS EQ 1. MOVE-CORRESPONDING LT_DRAFT_ACCOUNT TO LT_ACCOUNT. ELSE. RETURN. ENDIF. MOVE-CORRESPONDING LT_ACCOUNT[ 1 ] TO LS_ACCOUNT. IF LS_ACCOUNT-ISACTIVEENTITY EQ ABAP_TRUE. LV_UI_STATUS = '30'. LV_ACCOUNT_ACTION = '30'. ELSE. IF LS_ACCOUNT-HASACTIVEENTITY EQ ABAP_TRUE. LV_UI_STATUS = '20'. LV_ACCOUNT_ACTION = '20'. CALL METHOD ZTR_CL_ACC_APPLY=>CHECK_IF_CAN_FIOK EXPORTING IV_DEL_FLG = LS_ACCOUNT-DELFLG IV_ZDJZT = LS_ACCOUNT-ZDJZT IMPORTING EV_ENABLE = LV_ENABLE_FIOK. IF LV_ENABLE_FIOK = 'X'."数据审核完成,可以进行财务审核 LV_ACCOUNT_ACTION = '25'. ENDIF. ELSE. LV_UI_STATUS = '10'. LV_ACCOUNT_ACTION = '10'. ENDIF. ENDIF. SET_FIELD_CTRL( EXPORTING IS_CTX = IS_CTX IT_KEY = IT_KEY IO_READ = IO_READ IO_MODIFY = IO_MODIFY IV_ACCOUNT = LS_ACCOUNT IV_OPER = LV_ACCOUNT_ACTION IMPORTING EO_MESSAGE = EO_MESSAGE ET_FAILED_KEY = ET_FAILED_KEY ). ENDIF. ENDMETHOD. |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 |
METHOD SET_FIELD_CTRL. * BREAK YANGSEN. DATA: LT_ACTIVE_ACCOUNT TYPE ZTTRD_I_ACC_APPLY, LT_DRAFT_ACCOUNT TYPE ZTTRD_I_ACC_APPLY, LS_DRAFT_ACCOUNT TYPE ZSTRD_I_ACC_APPLY, LT_FIELD_STATUS TYPE FCLM_BAM_T_FIELD_PROPERTY, LV_FIELD_NAME1 TYPE NAME_KOMP, LV_FIELD_NAME2 TYPE STRING. DATA: LV_TABLE_TYPE TYPE REF TO CL_ABAP_TABLEDESCR, LV_STRUCT_TYPE TYPE REF TO CL_ABAP_STRUCTDESCR, LT_COMP_TAB TYPE CL_ABAP_STRUCTDESCR=>COMPONENT_TABLE. " LV_STRUCT_TYPE ?= CL_ABAP_TABLEDESCR=>DESCRIBE_BY_DATA( IV_ACCOUNT-NODE_DATA ). LV_STRUCT_TYPE ?= CL_ABAP_typeDESCR=>DESCRIBE_BY_DATA( IV_ACCOUNT-NODE_DATA ). LT_COMP_TAB = LV_STRUCT_TYPE->GET_COMPONENTS( ). DATA(LO_SET_PROPERTY) = NEW /BOBF/CL_LIB_H_SET_PROPERTY( IS_CONTEXT = IS_CTX IO_MODIFY = IO_MODIFY ). SELECT FIELD_NAME PROPERTY INTO TABLE LT_FIELD_STATUS FROM ZTRT_BOPF_FUCT_F WHERE FUNCT = 'ACCOUNTAPP' AND OPER = IV_OPER . CHECK LT_FIELD_STATUS IS NOT INITIAL. SORT LT_FIELD_STATUS BY FIELDNAME. LOOP AT LT_COMP_TAB INTO DATA(Ls_COMP_TAB). LV_FIELD_NAME1 = Ls_COMP_TAB-NAME. LV_FIELD_NAME2 = Ls_COMP_TAB-NAME. READ TABLE LT_FIELD_STATUS ASSIGNING FIELD-SYMBOL(<LS_FIELD_STATUS>) WITH KEY FIELDNAME = LV_FIELD_NAME1 BINARY SEARCH. IF SY-SUBRC <> 0 . READ TABLE LT_FIELD_STATUS ASSIGNING <LS_FIELD_STATUS> WITH KEY FIELDNAME = '*' BINARY SEARCH. ENDIF. IF SY-SUBRC <> 0. CONTINUE. ENDIF. CASE <LS_FIELD_STATUS>-PROPERTY. WHEN 'R'. LO_SET_PROPERTY->SET_ATTRIBUTE_READ_ONLY( EXPORTING IV_ATTRIBUTE_NAME = LV_FIELD_NAME2 " Name of the attribute for which the property is to be set IV_KEY = IV_ACCOUNT-KEY " Key of the instance for which the property is to be set IV_VALUE = ABAP_TRUE " New value of this property (true/false) ). WHEN 'M'. LO_SET_PROPERTY->SET_ATTRIBUTE_MANDATORY( EXPORTING IV_ATTRIBUTE_NAME = LV_FIELD_NAME2 " Name of the attribute for which the property is to be set IV_KEY = IV_ACCOUNT-KEY " Key of the instance for which the property is to be set IV_VALUE = ABAP_TRUE " New value of this property (true/false) ). WHEN 'H'. LO_SET_PROPERTY->SET_ATTRIBUTE_ENABLED( EXPORTING IV_ATTRIBUTE_NAME = LV_FIELD_NAME2 " Name of the attribute for which the property is to be set IV_KEY = IV_ACCOUNT-KEY " Key of the instance for which the property is to be set IV_VALUE = ABAP_FALSE " New value of this property (true/false) ). ENDCASE. ENDLOOP. ENDMETHOD. |
3.强制输入问题
如上代码后,当设置了强制输入(M)的字段时,在SAP Fiori Elements开发的APP中,此字段名上会加入一个红色的*,以代码此字段必输。

所以创建一个Validations:CHCK_VALUE_MANDATORY。如图

此时当在页面上字段变化 时,如此字段是强制 输入的,而此字段是空时就会所错,并提示些字段 不能为空了。