Web Dynpro ABAP for Practitioners
Ulrich Gellert
l
Ana Daniela Cristea
Web Dynpro ABAP for Practitioners
Ulrich Gellert c/o S þ P LION AG Robert-Bosch-Str. 9 68542 Heddesheim Germany
[email protected]
Ana Daniela Cristea c/o S + P LION AG Robert-Bosch-Str. 9 68542 Heddesheim Germany
[email protected]
ISBN 978-3-642-11384-0 e-ISBN 978-3-642-11385-7 DOI 10.1007/978-3-642-11385-7 Springer Heidelberg Dordrecht London New York Library of Congress Control Number: 2010929263 # Springer-Verlag Berlin Heidelberg 2010 This work is subject to copyright. All rights are reserved, whether the whole or part of the material is concerned, specifically the rights of translation, reprinting, reuse of illustrations, recitation, broadcasting, reproduction on microfilm or in any other way, and storage in data banks. Duplication of this publication or parts thereof is permitted only under the provisions of the German Copyright Law of September 9, 1965, in its current version, and permission for use must always be obtained from Springer. Violations are liable to prosecution under the German Copyright Law. The use of general descriptive names, registered names, trademarks, etc. in this publication does not imply, even in the absence of a specific statement, that such names are exempt from the relevant protective laws and regulations and therefore free for general use. All printed screens, SAP, the SAP Logo, my SAP, SAP R/3, ABAP, NetWeaver Portal are subject to copyright or are trademarks of SAP AG, Dietmar-Hopp-Allee 16, 69190 Walldorf, Germany Cover design: KuenkelLopka GmbH, Germany Printed on acid-free paper Springer is part of Springer Science+Business Media (www.springer.com)
Foreword
Taking Albert Einstein’s quote as a motto “Example isn’t another way to teach, it is the only way to teach”, our target was to create a book for explaining step-bystep the Web Dynpro ABAP to the reader. Assisted by practical examples, you will learn more and more about Web Dynpro ABAP, from chapter to chapter. Moreover, the connections with other areas are also pointed out by practical examples. In Chap. 1, we explain what means the Web Dynpro integrated in a SAP NetWeaver platform. Chapter 2 is about the “Easy Access” to a SAP System. In Chap. 3, we describe the modality to creating a Web Dynpro Component. We explain all the elements of a view through examples, and we show you how to use the ABAP Debugger to diagnose the Application. Chapter 4 gives attention to the ABAP Dictionary, where all the Development Objects are created. These ones are the basis for all our examples. With this knowledge, you will be able to easily create Web Dynpro applications. In Chap. 5, we present the Context Nodes and Attributes and explain their importance for the Web Dynpro. We consider the possibilities to create, use, fill in with data, and read the contents. In Chap. 6, we go into details with Data Binding, Context Mapping and Interface Methods. For this purpose, we present the Data Binding through simple examples. We change these examples step-by-step, to show you a clear picture of the context mapping (as well as in an internal and external way – Direct Mapping and Reverse Mapping). Chapter 7 covers the View Controller Methods, beginning with some examples of Hook Methods and ending with User Defined Methods and Event Handler Methods. Each method is explained by an example. Chapter 8 illustrates the layout of the UI Elements. In our largest chapter (Chap. 9), we describe in details the User Interfaces (UI). Each UI element is presented through an example. Moreover, we show the dynamic programming of these UI elements and give additional information.
v
vi
Foreword
Chapter 10 includes Messages and Exceptions. We start with the creation of the necessary classes (Message Class, Exceptions Class and Assistance Class) and we show you how to use them to create solid applications that catch exceptions and inform the user through messages. Chapter 11 is about creating Multilingual Applications on the levels of interfaces and master data. We also present how to use these data in the Web Dynpro components. In Chap. 12, we present several Web Dynpro Models. We show you not only how to use an Assistance Class, a Web Service or a BAPI, but also how to create Multi Component Applications. Chapter 13 covers the ABAP list viewer (ALV) and the Select options (SO). We start again with simple examples and build them up to an ALV output configuration in combination with SOs. In Chap. 14, it’s described the integration of Web Dynpro Applications in the SAP NetWeaver Portal. We present the connection with the back-end ABAP System, ending with WD applications that send and react to a portal event. The next Chapter (Chap. 15) is about Web Dynpro and Authorizations. We shortly present the Role Based Access Control (RBAC) model and describe the SAP NetWeaver authorization concept. In our last Chapter (Chap. 16), we would like to show how the Mind Map can help you to learn Web Dynpro ABAP easier and faster. We create a Mind Map that includes all the necessary Web Dynpro Elements. The examples in our book have been developed on a SAP System with SAP NetWeaver 7.0 and Support Package 17. From SDN (http://www.sdn.sap.com), you can download a free of charge SAP NetWeaver Trial Version with ABAP and SAP GUI, for testing. With this Trial Version, you can create most of our exercises. You’ll also find most of the configuration steps at SDN. To use the SAP interactive forms by ADOBE, you need both NetWeaver Trial Versions (ABAP and Java), because ADS is an integral part of the SAP NetWeaver Java version. Additionally, you need the ADOBE Live Cycle Designer from the SAP Service marketplace. The configuration steps required in this case are shown in the SAP PRESS book “SAP Interactive Forms by Adobe” (Hauser et al.). To be able to work with the portal, you need the SAP NetWeaver Java Trial Version. In the SAP PRESS book “Developer’s Guide to SAP NetWeaver Portal Applications” (Banner et al.), you will find all the software and hardware requirements, along with the configuration steps. The creation of a book takes time. Many discussions with students and developers made us think about writing a practical book on the Web Dynpro ABAP subject. The most important issue was to guide the reader step-by-step, with practical examples. Many weekends, holidays and evenings were invested in this book, and the positive feedback of our colleagues always gave us new energy.
Acknowledgements
We would like to thank our proofreaders Dieter Schmitt and Heinz-Ju¨rgen Gebhardt. Their advices and comments helped us a lot. Ulrich Gellert would like to thank all his colleagues of S+P LION AG for the useful input during the project. I also would like to thank my father, Gerhard Gellert, who unfortunately died too early. He introduced me into the world of IT in 1983 and, without him, our company could never become what it is. Special thanks go to my mother, Gabriele Gellert. She has been supporting me until today, and she is the heart of our company. Especially, I would like to thank my lovely wife Carmen and my children Alexa and Marc, for their support during the project. Ana Daniela Cristea gives special thanks to NWCON Technology Consulting, especially to Thomas Muschalik and S+P LION AG, for their great support. Taking this opportunity, I’d like to thank to the special persons who have been guiding me through my dissertation: Octavian Prostean and Mircea Vladutiu. Not to forget the people who encouraged me to publish my first books and articles: Aron Poanta and Caius Panoiu, thanking them for the useful advices. Last but not least, I would like to thank my family and friends. Especially to my mother, Sabina Cristea, and to Susanne and Edgar Hammes, who supported me with all their powers. They gave me the time I needed to be one of those who wrote this book for you.
vii
Contents
1
What is Web Dynpro? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
2
SAP Easy Access . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.1 Changing the SAP Easy Access . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.2 Favorites List . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.3 Setting a Transaction as Start Transaction . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.4 Creating a Shortcut . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5 6 6 8 8
3
Designing a Web Dynpro Component . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.1 View . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.1.1 View Layout . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.1.2 Context View . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.1.3 Actions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.1.4 Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.1.5 Properties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.1.6 Attributes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.2 Componentcontroller . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.3 Window . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.4 Application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.5 ABAP Debugger . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.6 Web Dynpro Logon Page Configuration . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
11 14 14 17 19 19 21 22 23 23 24 27 30
4
ABAP Dictionary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.1 Data Element . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.2 Domain . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.3 Structure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.4 Table . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.5 Search Help . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.6 Database View . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.7 Table Type . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.8 Lock Object . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
33 34 35 38 40 45 48 51 52 ix
x
Contents
Context Nodes and Attributes at Design Time . . . . . . . . . . . . . . . . . . . . . . . . 5.1 Attributes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.2 Nodes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.2.1 Creating a Node that Uses an ABAP Dictionary Repository Object . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.2.2 Working with Child Nodes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
59 64
6
Data Binding, Context Mapping and Interface Methods . . . . . . . . . . . . . 6.1 Data Binding . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.2 Context Mapping . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.2.1 Internal Context Mapping . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.2.2 External Context Mapping . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.3 Interface Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
67 67 72 72 76 83
7
View Controller Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87 7.1 Hook Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87 7.1.1 wdDoInit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88 7.1.2 wdDoExit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91 7.1.3 wdDoModifyView . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91 7.1.4 wdDoBeforeAction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96 7.1.5 wdDoOnContextMenu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98 7.2 Supply Function Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102 7.3 User-Defined Instance Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103 7.4 Fire Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 105 7.5 Event Handler Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109
8
Layout UI Elements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8.1 FlowLayout . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8.2 GridLayout . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8.3 MatrixLayout . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8.4 RowLayout . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
113 114 116 119 120
9
User Interface Elements (UI elements), Static and Dynamic Programming . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.1 Action . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.1.1 Timed Trigger . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.1.2 ButtonChoice . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.2 Selection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.2.1 DropDownByKey . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.2.2 DropDownByIndex . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.2.3 RadioButtonGroupByIndex . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.3 Layout . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.3.1 ViewContainerUIElement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.3.2 TabStrip . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.3.3 PageHeader . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.3.4 ContextualPanel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
123 124 124 126 132 132 135 137 140 140 146 149 152
5
55 56 58
Contents
10
11
12
xi
9.3.5 Tray UI Element . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.3.6 MessageArea . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.4 Complex . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.4.1 Table . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.4.2 RoadMap . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.4.3 PhaseIndicator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.4.4 Tree – Sequential Implementation . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.4.5 DateNavigator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.5 Graphic . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.5.1 Image . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.5.2 BusinessGraphics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.6 Integration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.6.1 The InteractiveForm . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.6.2 FileUpload . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
155 159 163 163 171 180 186 191 197 198 201 206 206 215
Messages, Exceptions and Web Dynpro ABAP . . . . . . . . . . . . . . . . . . . . . . 10.1 Message Handling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10.1.1 Dynamic Texts Stored in the Text Pool of the Assistance Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10.1.2 Text from Database Table T100 . . . . . . . . . . . . . . . . . . . . . . . . . . 10.2 Exception Handling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10.2.1 Exception Class with OTR Text . . . . . . . . . . . . . . . . . . . . . . . . . . 10.2.2 Exception Class with Text from a Message Class . . . . . . . .
221 222
Writing Multilanguage Applications . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.1 Creating Multilanguage User Interfaces . . . . . . . . . . . . . . . . . . . . . . . . . . 11.1.1 Internationalization of Data Elements Defined in ABAP Dictionary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.1.2 Internationalization of Domains Defined in ABAP Dictionary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.1.3 Internationalization of Text from OTR . . . . . . . . . . . . . . . . . . . 11.1.4 Internationalization of Text from Assistance Class . . . . . . . 11.1.5 Internationalization of Messages . . . . . . . . . . . . . . . . . . . . . . . . . . 11.2 Multilanguage Records in the Database . . . . . . . . . . . . . . . . . . . . . . . . . . 11.2.1 Study an Example Created in the System . . . . . . . . . . . . . . . . . 11.2.2 Creating Table Structures and Internationalization of the Records . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.2.3 Using the Internationalized Records in WebDynpro . . . . . Web Dynpro Model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12.1 Assistance Class as a Model for a Multicomponent Application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12.2 BAPI as a Model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12.2.1 Creating a BAPI . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12.2.2 Using the Created BAPI as a Model . . . . . . . . . . . . . . . . . . . . . . 12.3 Web Service . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
222 225 227 228 233 237 238 240 241 242 244 245 247 248 250 255 259 260 274 274 279 283
xii
Contents
12.3.1 12.3.2 12.3.3 12.3.4
Creating the Web Service . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Web Service Configuration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Testing the Web Service . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Consuming the Web Service in Web Dynpro . . . . . . . . . . . .
284 287 288 289
13
ALV and Select Options . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13.1 SAP List Viewer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13.1.1 Simple ALV Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13.1.2 ALV Configuration Model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13.2 Select Options . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13.3 ALV and Select Options . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
295 295 296 299 306 313
14
Integrating a Web Dynpro Application into the SAP NetWeaver Portal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14.1 Creating a Folder . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14.2 Connecting to the Back-End ABAP System . . . . . . . . . . . . . . . . . . . . . . 14.3 Creating an iView . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14.4 Creating a Role and Role Assignment . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14.5 Running the Application into the Portal . . . . . . . . . . . . . . . . . . . . . . . . . . 14.6 Triggering a Portal Event . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14.7 Reacting to a Portal Event . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14.8 Creating a Page . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14.9 Running the Application that Processes Portal Events . . . . . . . . . . .
315 316 317 321 324 327 327 329 331 333
15
16
Web Dynpro and Authorization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15.1 Role Based Access Control Pattern – RBAC . . . . . . . . . . . . . . . . . . . . . 15.2 Authorization Object Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15.3 Authorization Object . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15.4 Authorization Fields . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15.5 Creating a Single Role and Changing its Authorization Data . . . . 15.6 Creating the Web Dynpro Component . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15.6.1 Checking the Authorization of the Current User . . . . . . . . . 15.6.2 Assigning the User-Role and Running the Application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
335 337 338 338 340 343 346 346 349
Web Dynpro Mind Map . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 351 16.1 Creating a Mind Map . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 351 16.2 Web Dynpro ABAP Mind Map . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 352
Appendix . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 353 Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 357
Chapter 1
What is Web Dynpro?
“Logic will get you from A to B. Imagination will take you everywhere.” Albert Einstein
Abstract In this chapter, we present the place and role of the Web Dynpro within the SAP NetWeaver platform. So, we start with the layers of the SAP NetWeaver platform, we continue with the importance of the Application Platform layer, and we conclude with the place and role of Web Dynpro (ABAP and Java) within the Application Server ABAP and, respective, Application Server Java. To answer this question we have to look at the SAP NetWeaver technology platform (Fig. 1.1). As we can see, four layers are distinguished in this context: Application Platform, Process Integration, Information Integration and People Integration. The Application Platform represents the technical basis of almost all the other SAP products. This is the reason why the Application Platform plays a central role in the SAP NetWeaver. The Application Platform essentially offers two programming interfaces: ABAP and Java (J2EE). ABAP is the programming interface for Application Server (AS) ABAP and Java is the programming interface for AS Java. To create ABAP and Java applications, we have two independent development environments: ABAP Workbench for ABAP and SAP NetWeaver Developer Studio for Java. Both development environments offer the possibility to create web based applications built by using declarative programming techniques based on the Model View Controller (MVC) paradigm. SAP NetWeaver Developer Studio is the SAP’s own development environment used to develop Java-based multilayer business applications. This development environment is based on Eclipse and offers a Web Dynpro Perspective to create Web Dynpro Java applications (Fig. 1.2). All the tools we need to create Web Dynpro Java applications are found within the SAP NetWeaver Developer Studio. U. Gellert and A.D. Cristea, Web Dynpro ABAP for Practitioners, DOI 10.1007/978-3-642-11385-7_1, # Springer-Verlag Berlin Heidelberg 2010
1
2
1 What is Web Dynpro?
Fig. 1.1 SAP NetWeaver components (SAP)
Fig. 1.2 SAP NetWeaver Developer Studio – Web Dynpro perspective
ABAP Workbench is the SAP’s own development environment used to develop ABAP-based multilayer business applications. This development environment offers Web Dynpro Explorer to create Web Dynpro ABAP components (Fig. 1.3).
1 What is Web Dynpro?
Fig. 1.3 ABAP Workbench – Web Dynpro Explorer
The Application Server ABAP has the structure presented in Fig. 1.4.
Fig. 1.4 AS ABAP (SAP)
3
4
1 What is Web Dynpro?
As we can see, most of the AS ABAP components can be divided into three layers: l l l
Presentation layer. Business layer. Persistence layer.
Web Dynpro ABAP is part of the presentation layer and it’s the SAP standard UI technology used for developing web business applications without knowing HTML or JavaScript. Web Dynpro ABAP offers many advantages, as follows: l l l l l
Strict separation between the layout and business data. Re-use and better maintainability through reusability. Automatic input checks. Automatic data transport, using data binding. WYSIWYG (What You See Is What You Get) view editor.
Web Dynpro ABAP and Web Dynpro Java mostly offer the same functionalities. But, of course, there are some differences between them, for example: l
l
Web Dynpro Java, unlike the Web Dynpro ABAP, disposes of a ViewSet that allows us to integrate in a Screen more Views, by using certain pre-defined layouts. In this respect, their common part is the View Container UI Element. Web Dynpro Java offers graphical tools that ease the programming work, as: Navigation Manager and Diagram View, unlike the Web Dynpro ABAP where we dispose only of a tool used to visualize and to define the window structure.
The Web Dynpro ABAP is what the current book is about. More information about Web Dynpro Java can be found in the Book Inside Web Dynpro for Java by Chris Whealy.
Chapter 2
SAP Easy Access
“The way to get started is to quit talking and begin doing” Walt Disney
Abstract This chapter presents the SAP Easy Access, highlighting some aspects found in our everyday work. So, we show how to change the standard settings, how to add in the Favorites list the frequently used transactions, and how to create a Shortcut on the Desktop. SAP easy access starts automatically after logging-in into the SAP system. In the left side, we can see the user menu. Here are the functions the user needs to perform his tasks (Fig. 2.1).
SAP Easy User Menu
Fig. 2.1 SAP easy access
U. Gellert and A.D. Cristea, Web Dynpro ABAP for Practitioners, DOI 10.1007/978-3-642-11385-7_2, # Springer-Verlag Berlin Heidelberg 2010
5
6
2 SAP Easy Access
2.1
Changing the SAP Easy Access
We can change the SAP easy access settings through the menu Extras ! Settings, by specifying settings as follows: l l l l
The place of the Favorites The presents of the menu The easy access picture in the right side of the screen – to be present or not Displays or not the technical names (Fig. 2.2).
Fig. 2.2 Settings
2.2
Favorites List
The user menu is mostly defined by the administrator, but we can define our own Favorites list. Here, we can create our own list of favorites containing items as transaction, files, web addresses or other objects. To add new transactions in the Favorite list, we can choose from the menu Favorites ! Insert Transactions (Fig. 2.3).
Fig. 2.3 Inserting transaction onto the Favorites list
As a result, the new item appears in our Favorites list (Fig. 2.4). Fig. 2.4 Favorites list
We can find the list of the SAP transaction codes in the transparent table TSTC. Besides the transactions predefined in the system, we can create our own transactions (e.g. with transaction SE93) which are going to be inserted in this table.
2.2 Favorites List
7
Every time we use a transaction, the system verifies in this table whether the transaction exists and if we have the proper authorization to use it. As support for our daily tasks, we add here some of the transactions we use in this book (Fig. 2.5). Fig. 2.5 Transactions used
To add other objects, we can choose them from the menu Favorites ! Add Other Objects (Fig. 2.6).
Fig. 2.6 Adding new objects in Favorites list
8
2 SAP Easy Access
We add the web address to open the SDN page (Fig. 2.7).
Fig. 2.7 Inserting a web address
We can use Favorites ! Download to PC to save on our computer a list with all the objects we have in the Favorites folder. To upload in a Favorites folder objects from a list saved on our computer, we can use Favorites ! Upload from PC.
2.3
Setting a Transaction as Start Transaction
We have the possibility to set a transaction as start transaction: Extras ! Set start transaction (Fig. 2.8). In this way, the desired transaction is automatically started after logging-in into the system (in our case the SE80 transaction), and we don’t see the SAP easy access anymore.
Fig. 2.8 Setting the start transaction dialog box
2.4
Creating a Shortcut
After installing the SAP GUI, a SAP logon icon appears on our desktop. By using this logon, we can login into the system. Additionally, we can create a SAP logon shortcut to be used to perform the same logon, but we don’t need to fill all the entries in the logon form. A SAP shortcut allows us not only to perform a logon into the system, but to execute other commands, too. So, we can start a SAP transaction, run a report or perform a system command. To create a SAP Shortcut on our desktop to start the transaction SE80, we can use the Wizard available in the layout menu, by clicking on the respective icon located in the system function bar (Fig. 2.9).
2.4 Creating a Shortcut
9
Fig. 2.9 Creating a SAP Shortcut on our Desktop
Another possibility to create a SAP shortcut on our desktop is to select a transaction or another object from the Favorites list, and to use the menu Edit ! Create Shortcut on the Desktop.
Chapter 3
Designing a Web Dynpro Component
“Experience is something you don’t get until just after you need it” Steven Wright
Abstract The present chapter is dedicated to the constitutive elements of a Web Dynpro ABAP component. Moreover, we show how to use the ABAP Debugger to execute, by line or by section, a Web Dynpro application, and how to use the new tool offered by ABAP Debugger to reach the context attributes values. In order to develop a Web Dynpro ABAP component, we have to open the ABAP Workbench of the Application Server ABAP. To work with ABAP Workbench, we need an authorization as a developer or a developer key, and for the SAP NetWeaver ABAP trial version we can use BCUSER, automatically registered as a developer. Web Dynpro is available with release SAP NetWeaver 2004s and later. After logging into AS ABAP, we can use the transaction SE80 to call the object navigator (Fig. 3.1).
Fig. 3.1 Object navigator U. Gellert and A.D. Cristea, Web Dynpro ABAP for Practitioners, DOI 10.1007/978-3-642-11385-7_3, # Springer-Verlag Berlin Heidelberg 2010
11
12
3 Designing a Web Dynpro Component
All the repository objects we develop with the ABAP Workbench tool we build by using the Object Navigator. Here, we develop not only Web Dynpro applications, but also other development objects (e.g. reports, database tables, data elements, classes, function modules, etc). The development objects we create as customer have the first letter “y” or “z”. Therefore, we created a Web Dynpro component with the name y_wd_component. We have to assign all the development objects created with ABAP Workbench to a package. We can use the default package “$TMP” to create test programs without transporting, or we can create our own packages. We choose to create our own package, named Y_WEBDYNPRO (Fig. 3.2).
Fig. 3.2 Creating the package Y_WEBDYNPRO
We have chosen the package type “Not a Main Package”, because this package holds development object and not other packages. After creating the package, we create a Web Dynpro component, as follows: right-click on the package name and, from the context menu, we select Create ! Web Dynpro ! Web Dynpro component. We have to enter the component name, a short description, the type we want to create, the view name and the window name (Fig. 3.3).
Fig. 3.3 Creating a Web Dynpro component
3 Designing a Web Dynpro Component
After saving
13
our component, we have to assign it to our package (Fig. 3.4).
Fig. 3.4 Assigning the component to a package
As a result, in Object Navigator we can see the Package Y_WEBDYNPRO and our first created Web Dynpro Component (Fig. 3.5).
Fig. 3.5 The content of our package
The name of the development objects marked in blue are not active. After creating the Web Dynpro component, we have to activate it (Fig. 3.6).
14
3 Designing a Web Dynpro Component
Fig. 3.6 WD component activation
3.1
View
Each Web Dynpro application has at least one view. Each View has a view Layout, where we can add different UI (User Interface) elements that can be nested one in the other one, to create the screen. The positioning of the UI elements in a view is realized by using the layout and data layout. Each View has a view controller that is automatically created for this view and each View has several tabs (Properties, Layout, Outbound Plug, Inbound Plug, Attributes, Context, Actions and Methods). This indicates that a View consist of many parts.
3.1.1
View Layout
The screen content of a view is designed in the Layout tab. The View Layout is divided in three areas: l l l
UI element library View designer Context menus, UI elements properties and UI element hierarchy (Fig. 3.7).
Tip In case an error occurs and in the View Layout we can’t see UI Element Library and View Designer, we have to map the IP address to the host name, because the Web Dynpro ABAP uses a fully qualified domain name FQDN; in conclusion, the URLs that contain the IP addresses are not supported To realize this mapping, we use the HOSTS file (C:/Windows/system32/drivers/etc) where we enter the IP address and the host name, separated by (at least) one space In case an error occurs: “URL http://hostname:port/sap/bc/wdvd call was terminated because the corresponding service is not available” – we have to activate the respective service by using the SICF transaction
3.1 View
15
View Designer Context Menus UI elements hierarchy UI element Library
UI elements properties
Fig. 3.7 View Layout
The UI Elements are grouped in a library to be accessed via the View Layout. We have several ways to add an UI element into the view layout. For example: l
By right-clicking on the ROOTUIELEMENTCONTAINER (Fig. 3.8)
Fig. 3.8 Adding UI elements into the view
l
By dragging & dropping (Fig. 3.9).
All the UI Elements we enter into a screen are children of the node ROOTUIELEMENTCONTAINER and are represented as a hierarchy where ROOTUIELEMENTCONTAINER is the top of this hierarchy. With “Swap Root Element” we have the possibility to transform ROOTUIELEMENETCONTAINER from a Transparent Container into another UI element (Table, FlashIsland, Group, etc.). In this way, we can use, for example, the FlashIsland UI element to integrate Adobe Flex into our web Dynpro component. This transformation is possible only if the ROOTUIELEMENTCONTAINER doesn’t have any child UI elements.
16
3 Designing a Web Dynpro Component
Drag & Drop
Fig. 3.9 Adding UI elements into the view
In our ROOTUIELEMENTCONTAINER, we insert one Group UI element, one InputField UI element, one Label UI element, one TextView UI element and one Button UI element (Fig. 3.10).
Group Label InputField Button TextView
Fig. 3.10 View layout
If we select individual UI elements in the layout of a view, their properties are displayed in the Properties area. In this way, we can change the properties of each element. For example, we have changed the property design of the button UI element and the property state of the InputField UI element (Fig. 3.11). As a result of changing the property state of the InputField UI element from the Normal item to the required one, the label associated to this UI element becomes a red star and the end user knows that this value is mandatory. For a property, we can create fixed character strings, we can choose from a list, or we can bind properties to context nodes or attributes by using the Binding button. For the text property of an UI element Button, we have created a fixed character string “Save”. For the design property, we have chosen from the list one of the supported designs.
3.1 View
17
Fig. 3.11 UI element properties
We need to bind the value property of the InputField UI element and the text property of the TextView UI element. To be able to do this, we will create two context attributes. By using “Context Menus” we have the possibility to create, for an application, our own context menus displayed in the Browser when the user presses right click on an UI element. In standard mode, the web Dynpro Framework offers the default context menus with certain functionalities, e.g. hiding an UI element displayed into the Browser. After running the application, we can test this standard mode by rightclicking on the inputField UI element.
3.1.2
Context View
The data are stored in the context and the UI Elements are the only objects the user interacts with. Every View has a Context View where we can create context nodes and attributes. Via data binding, the context of a view controller provides a view with all the required data. For our application, we create two context attributes named NAME and GREETING, of STRING type (Fig. 3.12). To put the data on the screen and to read data from user, we connect the proper UI Elements properties with attributes or nodes. In our case, we connect the property value of the InputField UI element with the NAME attribute. To create a greeting for the user and to show it after the user presses the Save button, we connect the property text of the TextView UI element with the GREETING attribute. These connections are known as data binding (Fig. 3.13).
18
3 Designing a Web Dynpro Component
Fig. 3.12 Creating an attribute in context view
Fig. 3.13 Data binding
The effect of the binding is that, at runtime, any data changes are transported in both directions and these changes affect all the properties bound to this element.
3.1 View
3.1.3
19
Actions
Some of the UI Elements have special events that are linked with the user actions. The UI element Button is one of these UI elements and that’s why we have to create an action that reacts to the user interaction. To do this, we use the Action tab (Fig. 3.14).
Fig. 3.14 Creating an action
As we can see, each action has a corresponding event handler method, automatically generated by the Framework. An event handler method is a special method of a view controller that has the ONACTION prefix followed by the action name. For the SAVE action, the Framework generates the ONACTION event handler. After creating an action, we can assign it to an UI element that has attached an event (Fig. 3.15).
Fig. 3.15 Assigning an action to an UI element
After generation, this method is empty, but we can fill it with source code by using the Methods tab.
3.1.4
Methods
In the Methods tab of a View, we can find some types of methods (e.g. event handler methods, Hook methods, user-defined instance methods).
20
3 Designing a Web Dynpro Component
In our case, in the Methods tab we can find the Hook methods, automatically generated by the Framework, and our event handler method ONACTIONSAVE (Fig. 3.16).
Fig. 3.16 Methods tab
With double-click on the method name, we open the ABAP editor (Fig. 3.17). In this way, we can insert the source code.
Fig. 3.17 ABAP editor
The user enters his name that we use to show a greeting message with the help of textView UI element. To create a greeting for the end user, we concatenate his name with the string “WELCOME” and we pass this string value in the GREETING attribute. After this, we reset the inputField UI element. To do this, we pass an empty string into the NAME attribute bound to the corresponding UI element (Listing 3.1).
3.1 View
21
Listing 3.1 On action save event handler method
METHOD onactionsave . DATA: lv_name TYPE string, lv_greeting TYPE string. wd_context->get_attribute( EXPORTING name = `NAME` IMPORTING value = lv_name ). CONCATENATE ‘Welcome’ lv_name INTO lv_greeting SEPARATED BY space. wd_context->set_attribute( name = 'GREETING' value = lv_greeting ). CLEAR lv_name. wd_context->set_attribute( name = 'NAME' value = lv_name ). ENDMETHOD.
For more details about Methods, please see Chap. 7.
3.1.5
Properties
In the Properties tab, we can create a description text for our view, we have information about the view and about the person who created and changed this view. In this tab, we can set the view lifetime: l l
Framework controlled – controlled by Framework When visible – lifetime limited to its visibility. A view controller is always deleted as soon as the corresponding view is no longer displayed on the user interface. It is used when a view is displayed only once and not repeatedly. Additionally, Property tab offers the possibility to define the usages (Fig. 3.18).
Create Controller Usage
Fig. 3.18 Properties view
22
3 Designing a Web Dynpro Component
We can define a usage to be able to access the methods of another internal controller or of an interface controller, if the usage has been defined for an external component. To create a new usage in the Used Controller/Components table, we have to choose the Button Create Controller Usage. The table Used Controller/ Components includes a list with all the global controllers of our own component and, in case we define usages, this list includes the external component and its interface controller. In our case, we don’t use any external components. In the list we have only the global controller COMPONENTCONTROLLER. We have to specify that, for each view controller, the usage of the corresponding component controller is automatically created.
3.1.6
Attributes
Each View controller contains some attributes automatically generated by the Framework (Fig. 3.19).
Fig. 3.19 Attributes tab
The attribute WD_COMP_CONTROLLER is a reference variable of IG_ COMPONENTCONTROLLER type that we can use to access all the publicly accessible methods of the component global generated interface of the corresponding component controller. The attribute WD_THIS is a self-reference to local controller interface. This self-reference works similarly with the self-reference me found in the ABAP Objects. We can use it, for example, to call a user-defined method. The attribute WD_CONTEXT is a reference to the controller context. The IF_WD_CONTEXT_NODE interface provides several methods that enable us to obtain read and write access to a context node. Additionally, we can create our own attributes. These attributes are used to store application data that are not relevant for the UI elements and we don’t store in the context. To access these attributes, we use the self-reference: wd_this ! attribute_name
3.3 Window
3.2
23
Componentcontroller
By default, every Web Dynpro component has a component controller that acts as the central controller instance within the entire component (Fig. 3.20).
Fig. 3.20 Component controller
Data required across different views can be stored in his context. Besides the Context tab, each COMPONENTCONTROLLER disposes of tabs: Properties, Attributes, Events and Methods. Hereunder, in our examples, we will see how we can cross-component access the methods and the attributes defined here.
3.3
Window
A Window is an entity into which we embed all the views that will be used to construct the screen for the end user. When the user interacts with a view, their interaction will cause a request to the server. In response, one or more views that build the current screen will require to be replaced with other views. This is possible through navigation links among the various views in the window. Each Web Dynpro component can have several Windows. We have created only one Window, named W_default. A view or several Views are generally embedded in a Window. The first view created at the WD component creation is directly embedded into the Window. To embed other views in a Window, we can use dragging & dropping or right-clicking on the window name to choose between embedding an empty view or the View we have created. The Empty View is a special type of View, presented in the ViewContainerUIElement example (Fig. 3.21). In every window, at least one view is marked as default. A default view is the first view displayed when the window is called. The first embedded view is marked as default, but we can change it. To mark as default, after right-clicking on the view we choose Set as default from the contextual menu.
24
3 Designing a Web Dynpro Component
Fig. 3.21 Embed View
By using Inbound plugs and Outbound plugs, we define the navigation between views or windows. For a Window, these plugs can be of Standard, Startup or Resume type. As we can see, the Framework generates for each window an inbound plug of Startup type and an event handler method (Fig. 3.22). By using this event handler method, we can read, for example, the URL parameters from a Web Dynpro application.
Fig. 3.22 Default inbound plug for a window
For a View, we don’t have the possibility to define a specific plug type.
3.4
Application
After developing a Web Dynpro component, we need to provide the users with access to its functionality. To do this, we have to create a Web Dynpro Application (Fig. 3.23).
3.4 Application
25
Fig. 3.23 Creating an application
For each application, the Framework generates an URL. We find this URL in the Properties tab (Fig. 3.24).
Fig. 3.24 Application URL
In the same time, we can specify here how the Messages are handled: l
l
Show Message Component on demand – the Message Component is displayed only when we have a message. Always Display Message Component – the Message Component is always displayed on the screen, even when we don’t have any messages.
26
3 Designing a Web Dynpro Component
By using the Parameters tab, we can define our own parameters for the application or we can choose from the parameters offered by the Web Dynpro Framework (Fig. 3.25).
Fig. 3.25 Application parameters list
To run the application, we can use the Execute button past the URL into the browser (Fig. 3.26).
or we can copy and
Standard Context Menus
Fig. 3.26 Running the application
When the user interacts with the screen, specific adapter techniques are used to convert data and events, as part of the request response cycle, into the browser format as HTML, JavaScript or XML. In Fig. 3.27, we can see the generated source code for our WD component.
3.5 ABAP Debugger
27
Fig. 3.27 Generated source file
3.5
ABAP Debugger
If any errors occur in our Web Dynpro components, we can use the ABAP Debugger to execute our WD component, by line or by section. To work with the debugger, we can create Breakpoints at the point where the program should pause (Fig. 3.28).
Click
Fig. 3.28 Setting a Breakpoint
28
3 Designing a Web Dynpro Component
We run the application and, in the moment when the program flow reached the defined breakpoint, the ABAP Debugger is open (Fig. 3.29).
Fig. 3.29 ABAP Debugger
As we can see in the Process Information, the main component of the ABAP Debugger, we debug an HTTP application. The “Exclusive” represents the fact that the application we debug occupies a work process of the application server. By using the Buttons from the Control Area, we can control the program – Single flow. For example, we can choose to execute the program line by line – Continue. step, or to execute the program up to the next Breakpoint We can use the ABAP Debugger tools to have information about the variable (Fig. 3.30).
Fig. 3.30 Tool Component of the ABAP Debugger
By using the New Tool button , we can open a selection window that offers the possibility to access additional functionalities. In the Special Tools section, we can find the created tool, to be used for a better debugging of the Web Dynpro components (Fig. 3.31).
3.5 ABAP Debugger
29
Fig. 3.31 ABAP Debugger – New tool selection window
As we can see in Fig. 3.32, we are offered the possibility to have access to all the individual elements of the Web Dynpro component; we can see the view attributes, the view layout, the UI elements and data binding, the context structure and its attributes, etc.
Fig. 3.32 The ABAP debugger – web Dynpro ABAP tool
30
3 Designing a Web Dynpro Component
We are able to see not only the context structure, but also to display the runtime object, by choosing from the contextual menu Display Runtime Object (Fig. 3.33).
Fig. 3.33 Displaying the runtime object
These are only some of the ABAP Debugger capabilities that can be used along with other performance tools (for example, the transactions WD_TRACE_TOOLS, S_MEMORY_INSPECTOR), to help us to develop Web Dynpro applications.
3.6
Web Dynpro Logon Page Configuration
As we have seen, a logon page appears when running our application, where we have to provide some values, as follows: Logon Language, Client, User Password, etc. (Fig. 3.34).
Fig. 3.34 Example of a web Dynpro application logon page
3.6 Web Dynpro Logon Page Configuration
31
We can change the modality this logon page looks like and the modality we realize the user authentication, by using the SICF transaction (HTTP Service Hierarchy Maintenance). In the webdynpro ! sap hierarchy, each Web Dynpro application disposes of one corresponding entry. By using this transaction, we search for all the entries that begin with Y_WD_* and are created by our test user Gellert (Fig. 3.35).
Fig. 3.35 Searching for a service with the SICF transaction
We find the entry that corresponds to our created Web Dynpro component (Fig. 3.36).
Fig. 3.36 Entry corresponding to our Web Dynpro component
With double-click, we are allowed to view or/and to change this service. In the lower part of the Error Page tab, we can find the Configuration button for the system logon. Here, we can define our own settings by choosing from the lists, or we can use the global settings (Fig. 3.37).
32
3 Designing a Web Dynpro Component
Fig. 3.37 System logon configuration
As a result of our changes, in the logon page we have to provide only the User and the Password, through a popup window, and we are able to change our logon password (Fig. 3.38).
Fig. 3.38 Logon page
Chapter 4
ABAP Dictionary
“Mystery creates wonder and wonder is the basis of man’s desire to understand” Neil Armstrong
Abstract The following section details and describes the ABAP Dictionary. The main purpose of this chapter is to show how to realize all the development objects to be used in the future Web Dynpro applications. Therefore, we present not only the modality to create the various development objects in the ABAP Dictionary, but also the modality to use them in realizing Web Dynpro applications. We can create development objects in ABAP Dictionary, by using the transaction SE11 (ABAP Dictionary Maintenance) or the Object Navigator (Fig. 4.1).
Fig. 4.1 Development object with transaction SE11
ABAP programming language has a number of ten elementary data types that we can use in our programs. When we want to create global data types by using the ABAP Dictionary, we have to use dictionary built-in types. These predefined types are different from the elementary data types. We need them for reasons of compatibility with the external data types. U. Gellert and A.D. Cristea, Web Dynpro ABAP for Practitioners, DOI 10.1007/978-3-642-11385-7_4, # Springer-Verlag Berlin Heidelberg 2010
33
34
4 ABAP Dictionary
In Fig. 4.2, we presented some of the ABAP Dictionary Built-In types and a few corresponding examples of Dictionary built-in data types and ABAP elementary types. Dictionary – ABAP type Example CHAR – c DATS – d INT4 – i NUMC – n STRING – string TIMS – t RAW - x RAWSTRING- xstring FLTP - f DEC - p
Fig. 4.2 Some of ABAP Dictionary Built-In types and corresponding ABAP elementary types
4.1
Data Element
A data element defines an elementary data type and has certain properties. We create a data element YDATEOFBIRTH (Fig. 4.3).
Fig. 4.3 Definition of a data element
4.2 Domain
35
In the “Data Type” tab we can choose between the elementary type and reference type. The elementary type can be a domain and a build-in type. In this case, we have chosen the build-in type DATS that has a predefined format (YYYYMMDD) and a predefined length 8. In the tab “Field Label”, we can set a field label that is automatically shown in the label, or caption of an UI Element that is bound to an attribute of this type. For a data element, we can create documentation F1 Help with Goto ! Documentation ! Change. This documentation is not seen on screen if the Web Dynpro application attribute WDHIDEMOREFIELDHELPASDEFAULT was set as ABAP_TRUE. We create a text that describes the content of our data element (Fig. 4.4).
Fig. 4.4 Creating a F1 help for a data element
4.2
Domain
A domain defines a value range. To be able to use it in a Web Dynpro application, in other repository object, as parameter in GUI programming, etc. we have to assign it to a data element (Fig. 4.5).
36
4 ABAP Dictionary
Fig. 4.5 Data elements and domains
We create a domain named Y_COUNTRY_DOMAIN that holds all the names of EU member states, with the proper abbreviation. In “Definition” tab we have to specify properties as data type, number of characters or length of output (Fig. 4.6).
Fig. 4.6 Definition of a domain – tab “Definition”
In “Value Range” we have three possibilities: l l l
Single values Intervals Value table
4.2 Domain
37
We begin with the first possibility, “Single values”. We define the domain fixed values – all the abbreviations of the EU countries, and a short text – the corresponding country names (Fig. 4.7).
Fig. 4.7 Definition of a domain – tab “Value Range”
As we have specified, to be able to use a domain we have to assign it to a data element. To do this, we create a new data element and we choose the elementary type – domain (Fig. 4.8).
Fig. 4.8 Assigning a domain to a data element
When we use this data element in our Web Dynpro application, for example to define a parameter or a context attribute, the user is allowed to choose only the values that range among values we have defined in Domain. To explain the next possibility (“Intervals”), we take an example where we need to store, in a table column, the ages between 18 and 45. In this case, we can use an interval to limit the values that the user may enter (Fig. 4.9).
38
4 ABAP Dictionary
Fig. 4.9 Definition of a domain – interval
We use this interval in the database table YPERSON, defined hereinafter. For this, we assign it to a data element Y_DEINTERVAL. To explain the last possibility (“Value Table”), we use a domain that is defined in the system: WAERS (Fig. 4.10).
Fig. 4.10 Domain WAERS – value table
It is recommendable to use the value table when we have many fixed values. In our case, we have used the system table TCURC. This table holds all the system currency. We use this value table in the database table YEU_COUNTRIES, defined hereunder. For this, we assign it to a data element Y_CURRENCY.
4.3
Structure
Structures consist of any combination of other data types of the ABAP Dictionary. In Fig. 4.11, we present a structure with three components: FIRSTNAME, LASTNAME and DATEOFBIRTH.
4.3 Structure
39
Fig. 4.11 Definition of a structure
For each component it is defined a component type, as follows: a data element, other structure, table type, etc. As a component type for a structure, we can choose a type that is already defined in the ABAP Dictionary, or we can create a new type. For example, the component DATEOFBIRTH has YDATEOFBIRTH data type. This data type has been already defined. If we want to create a new type for a component, we have to enter its name (for example, YFIRSTNAME) and then, with double-click, we can choose the new type (Fig. 4.12).
Fig. 4.12 Creating a new component type
After we create a structure, we have to maintain the enhancement category: Extras ! Enhancement Category, from the menu. In case we don’t want to further extend the component structure, we choose “Cannot be Enhanced” (Fig. 4.13).
Fig. 4.13 Maintaining enhancement category
40
4 ABAP Dictionary
We can use the structures defined in ABAP Dictionary to create the context node structure for a Web Dynpro application.
4.4
Table
We create two transparent tables, YPERSON and YEU_COUNTRIES. We will use this table later, for our Web Dynpro example. In the YPERSON table, we want to store the competition candidates. All the candidates should be 18–45 years old and live in an EU country. After creating the table, we have to enter a short description along with the delivery and maintenance (Fig. 4.14).
Fig. 4.14 Table maintenance
We set “Data Browser/Table View Main” ! Display/Maintenance Allowed, to be able to populate our table with values, using “Create Entries”, from the menu. Then, we will define our table structure. To do this, we select the tab “Fields” and enter the table columns (Fig. 4.15). For the fields MANDT and ID_PERSON, we have marked the option “Key”, meaning they are the table keys. The field MANDT is the SAP client field, a three-character client ID. The field “ID_PERSON” represents the candidate’s ID, required to uniquely identify each competition candidate.
Fig. 4.15 Table structure
4.4 Table
41
As can be seen, we have used the data elements created hereinbefore: YFIRSTNAME, YLASTNAME, Y_DEINTERVAL, Y_DEFORDOMAIN. When we want to create a new data element, we write its name and, with double-click, we activate the forward navigation. If this data element doesn’t exist, we are asked if we want to create the new data element (Fig. 4.16). Fig. 4.16 Creating a data element
Before being able to activate this table, we have to maintain the technical settings (Fig. 4.17).
Fig. 4.17 How to maintain the technical settings for the table YPERSON
We choose a size category 0, because we don’t require many data records. We have to maintain the enhancement category: Extras ! Enhancement Category, from the Menu. We choose the same “Cannot be Enhanced”, because we shouldn’t further extend the table structure. After this, we can activate our table and create the second table YEU_COUNTRIES. We hold here all the EU Member states information, as follows: country
42
4 ABAP Dictionary
name, year of EU entry, political system, capital city, currency and the flag image name. The structure of this table is presented in Fig. 4.18.
Fig. 4.18 Table structure
After this, we have to define a foreign key for the field CHECK_CUR. For this purpose, we use the button “Foreign Keys”. We are asked if we want to use the value table TCURC as check table (Fig. 4.19).
Fig. 4.19 How to create foreign key
We need TCUC as a check table, because we want to use its table contents, respectively the Currency Codes (Fig. 4.20).
4.4 Table
43
Fig. 4.20 Currency codes
After we maintain the Technical settings and enhancement category, we can activate the same as for the table YPERSON. The candidates can live only in an EU country. Therefore, we create a 1 to CN relationship between the tables. From the table YPERSON field ID_COUNTRY, we create a foreign key, (Fig. 4.21).
Fig. 4.21 How to create a foreign key
44
4 ABAP Dictionary
The system can generate the graphical representation of the relationships we have defined between tables. To show this graph, we use the Button “Graph” (Fig. 4.22).
Fig. 4.22 Foreign key relationship
We can see our tables YEU_COUNTRIES, YPERSON and the 1:CN relationship. The table TCUC is the check table for the table YEU_COUNTRIES. To see this relationship also, we have to select the name of YEU_COUNTRIES table and to press the Button “Check Table” (Fig. 4.23).
Fig. 4.23 Foreign key relationship
We can create contents with Utilities ! Table content ! Create Entries from Menu (Fig. 4.24).
4.5 Search Help
45
Fig. 4.24 Insert – table YEU_COUNTRIES
To display the content: Utilities ! Table content ! Display from Menu (Fig. 4.25).
Fig. 4.25 Select – table YEU_COUNTRIES
Tip With Utilities ! Database Object ! Database Utility or through the transaction SE14, we can use the Database Utility to activate and adjust a database table, in case we have changed its structure and an activation error is shown. We can use the Database Utility not only to activate and adjust a database, but also for other basic functions, as to create or delete a database table
We can use the transparent tables defined in the ABAP Dictionary to create the context node structure for a Web Dynpro application.
4.5
Search Help
ABAP Dictionary offers the possibility to create simple search help and collective search help. To create a search help, we can use the context menu of our package (Fig. 4.26).
46
4 ABAP Dictionary
Fig. 4.26 Creating a development object in the ABAP Dictionary by using the Object Navigator
We create a simple search help YSH_ID_PERSON for the column ID_PERSON of the table YPERSON (Fig. 4.27).
Fig. 4.27 Creating a simple search help
As can be seen at Data collection ! Selection method, we have used the table name YPERSON. This means that all the data required come from our table YPERSON. A search help can have the following parameters: “import parameters”, “export parameters” or “no import” and “no export”. We have used ID_PERSON as export parameter, because we want its value to be returned to the input template. LPos represents the parameter position in the hit list: FIRSTNAME has the position
4.5 Search Help
47
1 and it is firstly displayed in the hit list, and LASTNAME has the position 2, being displayed after the FIRSTNAME. We can test a search help (Fig. 4.28).
Fig. 4.28 Testing a search help
Afterwards, we want to use this search help in a Web Dynpro application. We create a search option for a competitor. The user has to enter the competitor’s ID into a search mask. The list of IDs is limited to the number of competitors. When the user doesn’t know the competitor’s ID, he uses the search help and can choose the competitor’s name. The content of the ID_PERSON parameter is returned to the search mask as soon as the user has selected a line of the hit list in the input help. In this way, we facilitate the input. We can use this search help if we link it with the ID_PERSON column of the YPERSON table. To do this, we select the column ID_PERSON and press the button “Srch Help” (Fig. 4.29).
Fig. 4.29 Search Help for the field ID_PERSON
48
4 ABAP Dictionary
After we enter the search help name, we have to create the search help attachment, and to save and activate the table (Fig. 4.30).
Fig. 4.30 How to create search help attachment to the column ID_PERSON
In this way, we have created a simple search help for the column ID_PERSON of the table YPERSON. When we use this column in Web Dynpro, the Framework creates a special icon to be used at the runtime to call the input help. Moreover, we can use the keyboard key F4 to call an input help. To be able to access a search help from a WD component, the proper Input Help Mode context attribute property has to be set (“Automatic” or “Dictionary Search Help”).
4.6
Database View
By using a view, we can combine the data distributed in several tables. For a better understanding, we create a view on the tables YPERSON and YEU_COUNTRIES. When we create a view, we can choose one of the four view types (Fig. 4.31).
Fig. 4.31 View types
4.6 Database View
49
We choose to create a database view named YVIEW_CMPETITION. At the beginning of the “view definition”, we have to select the view base table (in our case, the table YPERSON). After the base table definition, we link this table by defining the joining conditions. To create this link, we use the button “Relationships” (Fig.4.32).
Fig. 4.32 Creating a view
As result, the join conditions are generated (Fig. 4.33).
Fig. 4.33 Joining conditions
In the next step, we have to select the fields we need in our view. We can enter each field manually or we can use the Button “Table fields” (Fig. 4.34).
50
4 ABAP Dictionary
Fig. 4.34 View fields
After activation, we can see our view content using the “Contents Button” (Fig. 4.35).
Fig. 4.35 View content
In this way, we have created a database view on the tables YPERSON and YEU_COMPETITION (Fig. 4.36).
Fig. 4.36 View definition on the database
4.7 Table Type
51
By using this view, we can create the context node structure for our Web Dynpro application and so we simultaneously select the logically connected data, from two tables.
4.7
Table Type
We create a table type named YTABLE_TYPE, the line type being our YPERSON table (Fig. 4.37).
Fig. 4.37 Creating a table type
For the line type, we can use an existing type (table, structure, view, . . .) or we can enter the data type, length and number of decimals. The typical use of table type is the declaration of an internal table. Another example of using table type is to populate with values a context node via a supply function. To be able to do this, we create a table type named YTABLE_ TYPE_STRUCTURE with the line type – the structure YSTR_PERSON (Fig. 4.38).
Fig. 4.38 Table type – line type structure
In the next chapter, we show how we can use this table type to populate a context node.
52
4.8
4 ABAP Dictionary
Lock Object
We create a Lock Object for the database table YPERSON (Fig. 4.39). The lock object name has to begin with the prefix E (from “Enqueue”).
Fig. 4.39 Lock object
Our case consists of exactly one table, and the lock argument is the primary key of this table. The lock mode is set to write, but can be overwritten. After the lock object activation, the ABAP Dictionary generates two Function Modules, named ENQUEUE_
and DEQUEUE_. The Function Modules with enqueue prefix help us to set a lock, and the Function Modules with dequeue prefix help us to release the locks. With the SE37 transaction we can see the two generated Function Modules: ENQUEUE_EYPERSON and DEQUEUE_EYPERSON. Figure 4.40 shows the structure of the Function Module required to set a lock.
Fig. 4.40 Function Module for lock setting
4.8 Lock Object
53
SAP offers a lock mechanism required to provide two transactions by simultaneously changing the same data in the database. The lock table represents a table in the memory of the enqueue server and is used to manage all the locks in the system. This lock table is checked every time when the enqueue server receives a lock request. A program sends, to the lock table, the key of the table entries it wants to lock; if no lock is set, the request is accepted and the new lock is written in the lock table. If a lock is set, the request collides with an existing lock and the request is rejected.
Chapter 5
Context Nodes and Attributes at Design Time
Well done is better than well said. Benjamin Franklin
Abstract This chapter mainly focuses on the context nodes and attributes statically realized at design time. In this respect, we will explain not only the role and modality to create context nodes and attributes, but also the modality to access the values stored in the attributes of the nodes. An attribute is a context entity that has certain properties and can be directly created in the root node CONTEXT, or as a child for another node. Usually, a node is used to group more attributes that belong together. In Fig. 5.1, we present a context example created in a view context. A context node can have attributes or can hold other nodes, but a context attribute cannot have other attributes or nodes. We create a hierarchical arrangement that has, as the start point, the root node CONTEXT. This is automatically created when the controller is initialized and all the nodes and attributes we created are children of this root node.
Independent node Attributes of STUDENT node Independent node Dependent node or child node for FACULTY Attributes of ADDRESS node Attributes of Faculty node Attribute created in context
Fig. 5.1 Example of the structure of a View Context
U. Gellert and A.D. Cristea, Web Dynpro ABAP for Practitioners, DOI 10.1007/978-3-642-11385-7_5, # Springer-Verlag Berlin Heidelberg 2010
55
56
5 Context Nodes and Attributes at Design Time
The data hold in the context nodes and attributes are transient, they exist only for the lifetime of the controller. After this, all the data are lost if we don’t store them in storage media (e.g. database table).
5.1
Attributes
To create an attribute, we have to select the node where the attribute should be inserted (in this case, the root context node) and, with right-click, to open its context menu (Fig. 5.2).
Fig. 5.2 Creating an attribute
We have to enter the attribute properties – name and type are required, but the other settings are optional (Fig. 5.3).
Fig. 5.3 Defining the attribute properties
As data type for an attribute, we can use a data type as string, xstring, d, i or we can use the data type defined in the ABAP Dictionary. In our example, the attribute type YDATEOFBIRTH is a data element defined in the ABAP Dictionary. In the system, we find a list with all the data types we can use for an attribute (Fig. 5.4). The coding presented in Listing 5.1 shows how we can access, in a method, the value of the attribute created in the context node.
5.1 Attributes
57
Fig. 5.4 Searching for an attribute data type DATA lv_dateofbirth type ydateofbirth. wd_context->get_attribute( EXPORTING name = 'DATEOFBIRTH' IMPORTING value = lv_dateofbirth ).
Listing 5.1 Access of an attribute from context node
We have defined a local variable named lv_dateofbirth of YDATEOFBIRTH type, the same type as the attribute. We pass the value of the attribute DATEOFBIRTH in our local variable, by using the method get_attribute of the interface if_wd_context_node. The interface if_wd_context_node has many methods we can use to work with context nodes. We can see all the available methods of this interface by double-clicking on the get_attribute method. To set the value of an attribute, we can use the method set_attribute of the same interface. As can be seen in Fig. 5.4, the property Input Help Mode of the attribute is set AUTOMATIC. This means that it is used the search help assigned to the data type of the context attribute in the ABAP Dictionary. In principle, we have a data element of D type. This is the reason why we will have a CALENDAR as input help (Fig. 5.5).
Fig. 5.5 Calendar input help
58
5 Context Nodes and Attributes at Design Time
The read-only property set “no” means that the attribute is not write- protected. To put data on the screen and to read data from user, we connect the proper UI Elements properties with the attributes or nodes. The data are stored in the attributes, the UI Elements being the only object the user interacts with. For our example, we have an UI Element InputField where the user enters his date of birth. Web Dynpro Framework transports these data from the UI element to the attribute DATEOFBIRTH when the user presses the SAVE Button, after he enters the value. The attribute keeps the value for further processing. To be able to access the value of this attribute in our methods, we have to pass this value in a local variable (lv_dateofbirth). We can use this value, change it or pass the new value back in the context (Fig. 5.6). This value is kept in the context for the lifetime of the controller. Then, these data are lost if we don’t store them.
ABAP Dictionary
Fig. 5.6 Connection among attribute, ABAP Dictionary, method and UI Element
5.2
Nodes
We can directly create a node in the context root node or as child for other node. In Fig. 5.7 we show how we can create a node.
Fig. 5.7 Creating a node
5.2 Nodes
59
For each node we create, we have to set some properties, as: cardinality, selection, etc. We can individually create the attributes for a node, or we can use some repository objects from the ABAP Dictionary. For example, when we work with tables, structures or views defined in the ABAP Dictionary, we can use them to define our node, and the attributes will be automatically generated.
5.2.1
Creating a Node that Uses an ABAP Dictionary Repository Object
We create a context node that uses the ABAP Dictionary structure YSTR_PERSON (Fig. 5.8).
Fig. 5.8 Node properties
The Button “Add Attribute from Structure” allows us to add all the structure components or only a part of them (Fig. 5.9).
Fig. 5.9 Selecting components of Structure
60
5 Context Nodes and Attributes at Design Time
Because we need a proper attribute for all these structure components, we select all of them. As result, we have created a node, the attributes being automatically generated according to the structure components we have selected (Fig. 5.10).
Fig. 5.10 Context node STUDENT at design time
The properties of the node we have chosen are: cardinality 0. . .n, singleton – yes and Init. Lead Selection – yes. The cardinality properties are very important, because they tell us how many elements a context node may have at runtime. We have four possible values: l l l l
1. . .1 Exactly one context element is instantiated 0. . .1 Maximum one context element is instantiated 0. . .n Zero or more context elements are instantiated 1. . .n One or more context elements are instantiated
The singleton property can be set YES or NO. When a node is singleton at the runtime, we have only one instance of this node. As usage example, for a nonsingleton node we can specify the context structure required for a Tree UI Element – sequential implementation. The Lead Selection Initialization property determines if the lead selection should be automatically set or manually programmed. In our case, this property is set “YES”, meaning that the lead selection is AUTOMATIC and the first element of this node it automatically selected. More details about lead selection – Table UI element. For our node, we have defined the supply function named supply_student. Each node may have a supply function defined for it and automatically called by the Web Dynpro Framework. The scope of using a supply function is to populate a context node. In certain cases, we can use the Hook Method wdDoInit instead of a supply function. For more details, see the Hook Methods chapter. The coding presented in Listing 5.2 shows how we can use the supply function method to populate the context node STUDENT with three values. We have defined two variables: ls_student and lt_student. Ls_student is of type if_view_name=>element_student, where “view_name” represents the view name and “student” represents the node name. ”if_view_name” represents the programming interface for our view controller. By double-clicking on his name or clicking on the icon Display Controller Interface ( ), we can see the
5.2 Nodes Listing 5.2 Example of supply function Method
61 METHOD supply_student . DATA ls_student TYPE if_view_name=>element_student. DATA lt_student LIKE TABLE OF ls_student. ls_student-firstname = 'Ionescu'. ls_student-lastname = 'Ana Maria'. ls_student-dateofbirth = '19700309'. APPEND ls_student TO lt_student. ls_student-firstname = 'Marinescu'. ls_student-lastname = 'Loredana'. ls_student-dateofbirth = '19800523'. APPEND ls_student TO lt_student. ls_student-firstname = 'Marton'. ls_student-lastname = 'Luminita'. ls_student-dateofbirth = '19831108'. APPEND ls_student TO lt_student. node->bind_table( new_items = lt_student ). ENDMETHOD.
coding of this interface. Listing 5.3 shows a coding part for the context node STUDENT.
Listing 5.3 Example of view controller programming interface
….. constants: wdctx_Student type string value `STUDENT`. types: Element_Student type YSTR_PERSON, Elements_Student type standard table of Element_Student with default key. ……
As can be seen, Element_Student is of YSTR_PERSON type (our ABAP Dictionary structure). But, when we manually create context nodes without dictionary structure, in the view controller programming interface, a new structured type is created (Listing 5.4).
Listing 5.4 Example of view controller programming interface
….. types: begin of Element_Faculty, FACULTY_NAME type String, SPECIALIZATION type String, end of Element_Faculty, ……
This is why we use the following form to append values: ls_student-firstname ¼ ‘Ionescu’.
62
5 Context Nodes and Attributes at Design Time
The way we append values in an ABAP structure is: structure_name-component_name ¼ value With the declaration “DATA lt_student LIKE TABLE OF ls_student”, we declare an internal table. We use APPEND statement to add each new line at the end of the last line of the internal table. At the end, we use the bind_structure method to populate the node with values. Instead of the declaration: DATA ls_student TYPE if_view_name=>element_student. we can use: DATA ls_student TYPE wd_this->element_student. In this way, we don’t need the view name anymore, because we use the wd_this self-reference. The runtime structure is presented in Fig. 5.11. Root Node Node STUDENT Ionescu Ana Maria
19700309 Marinescu Loredana
19800523 Marton Luminita
Element 1
Element 2
Element 3
19831108
Fig. 5.11 The runtime structure
The node STUDENT was set Singleton, it has only an instance at runtime and the cardinality was set 0. . .n, meaning that, at runtime, we can have from zero to n elements. Because the lead selection was set “YES”, it was selected the first element of the node. To read, set or append a context node or attribute, we can use the Web Dynpro Code Wizard (Fig. 5.12). The option “As table operation” can be used in combination with the Read, Set or Append options for a node that allows the usage of this combination. We can read, for example, the entire context node STUDENT in an internal table. DATA lt_student TYPE wd_this->elements_student. lr_node->get_static_attributes_table( IMPORTING table = lt_student).
5.2 Nodes
63
Fig. 5.12 Web Dynpro Code Wizard, reading a context node or attribute
In this case, the wizard has generated a variable lt_student of type wd_this-> elements_student. In Listing 5.3 we saw that, in Interface Controller, besides the definition of a variable, the Element_structure Framework has also defined a variable Elements_Student, with the form: Elements_Student type standard table of Element_Student with default key. This is the reason why the Wizard offers the possibility to read all the values from the STUDENT node in lt_student. As we have mentioned in the last chapter, we can use a table type to populate with data a context node via a supply function. Our node STUDENT has its attributes from the YSTR_PERSON structure. The table type YTABLE_TYPE_ STRUCTURE defined in the ABAP Dictionary has the same YSTR_PERSON structure, as line type. Listing 5.5 shows how we can use a table type to populate with data a context node.
Listing 5.5 Example of supply function Method
METHOD supply . DATA: lt_student TYPE ytable_type_structure . DATA: ls_student TYPE ystr_person. ls_student-firstname = 'Ionescu'. ls_student-lastname = 'Ana Maria'. ls_student-dateofbirth = '19700309'. APPEND ls_student TO lt_student. ls_student-firstname = 'Marinescu'. ls_student-lastname = 'Loredana'. ls_student-dateofbirth = '19800523'. APPEND ls_student TO lt_student. node->bind_table( new_items = lt_student ). ENDMETHOD.
64
5 Context Nodes and Attributes at Design Time
5.2.2
Working with Child Nodes
We create the context structure presented in Fig. 5.13. Fig. 5.13 Example of child node
It has a context node FACULTY, cardinality 1. . .1, Singleton with child node ADDRESS, cardinality 1. . .1, Singleton and two attributes FACULTY_NAME type STRING and SPECIALIZATION type STRING. We read data from the attributes of the node ADDRESS as a child node for FACULTY. Listing 5.6 shows a possible method to read these attributes. DATA: lr_node TYPE REF TO if_wd_context_node, lr_subnode TYPE REF TO if_wd_context_node. DATA: lv_street TYPE string, lv_number TYPE y_char, lv_city TYPE string. lr_node = wd_context->get_child_node( 'FACULTY' ). lr_subnode = lr_node->get_child_node( 'ADDRESS' ). lr_subnode->get_attribute( EXPORTING name = 'STREET' IMPORTING value = lv_street ). lr_subnode->get_attribute( EXPORTING name = 'NUMBER' IMPORTING value = lv_number ). lr_subnode->get_attribute( EXPORTING name = 'CITY' IMPORTING value = lv_city ).
Listing 5.6 Reading the attributes values of the child node “ADDRESS”
With the first data definition, we create two variable lr_node and lr_subnode of if_wd_context_node type. With the second data definition, we create three variables with the same data type as the attributes we want to read. Data type Y_CHAR represents a data element defined in the ABAP Dictionary of CHAR type, length 6. Instead of the declaration: lr_node ¼ wd_context->get_child_node( ’FACULTY’). we can use the form: lr_node ¼ wd_context->get_child_node( name ¼ wd_this->wdctx_faculty).
5.2 Nodes
65
In the first case we have to write with capital letters the node name, and in the second case we use the constant wdctx_faculty of string type, defined by the Framework in Interface Controller, with the form: constants: wdctx_faculty type string value ‘FACULTY’. By using the get_child_node method of if_wd_context_node interface, we successively access the node FACULTY and the node ADDRESS, and by using the method get_attribute, we pass the values of the attributes in our local variable. Another possibility to read the values of the ADDRESS child node attributes is presented in Listing 5.7. DATA: lr_node TYPE REF TO if_wd_context_node, lr_subnode TYPE REF TO if_wd_context_node, ls_subnode type wd_this->element_address. DATA: lv_street LIKE ls_subnode-street, lv_number LIKE ls_subnode-number, lv_city LIKE ls_subnode-city. lr_node = wd_context->get_child_node( 'FACULTY' ). lr_subnode = lr_node->get_child_node( 'ADDRESS' ). lr_subnode->get_static_attributes( IMPORTING static_attributes = ls_subnode ). lv_street = ls_subnode-street. lv_number = ls_subnode-number. lv_city = ls_subnode-city.
Listing 5.7 Reading the attributes values of the child node “ADDRESS”
In this case, we have used the get_static_attributes method that supplies a copy of all the static attributes for the ADDRESS child node. After this, we are able to access the attributes values through the local structure “ls_subnode”. Listing 5.8 shows how we can populate with values the elements of the ADDRESS child node.
DATA: lr_node TYPE REF TO if_wd_context_node, lr_subnode TYPE REF TO if_wd_context_node, ls_subnode TYPE if_view_name=>element_address. lr_node = wd_context->get_child_node( 'FACULTY' ). lr_subnode = lr_node->get_child_node( 'ADDRESS' ). ls_subnode-street = 'Pforzheimer'. ls_subnode-number = '106A'. ls_subnode-city = 'Pforzheim'. lr_subnode->set_static_attributes( ls_subnode ).
Listing 5.8 Populating the attributes of the ADDRESS node
Chapter 6
Data Binding, Context Mapping and Interface Methods
You can’t stay in your corner of the forest waiting for others to come to you. You have to go to them sometimes. A. A. Milne
Abstract This chapter starts with the presentation of the mechanism used to manipulate data between the context attributes and UI elements, mechanism called, in Web Dynpro, “data binding”. We continue with the mechanism of sharing data among the various controllers, which is realized by using different variants of context mapping. Finally, we highlight the importance of the interface methods required to access them “cross-component”. In the last chapter, we have created context nodes and attributes in the context view. A node or attribute can be created in each context. When we create an attribute in the context view, this value is visible only in this context view. The mechanism for sharing data among different controllers is known as “context mapping”. A context mapping can be internal, when the nodes we map are within the same component, and external, when the mapping is cross-components. To put data on the screen and to read data from users, we have to link the UI elements properties with the proper context attributes. This process is known as “data binding”. All the data we show to the user or read from the user by using Web Dynpro are manipulated through context nodes and attributes.
6.1
Data Binding
Each UI element has certain properties. With data binding, we define which node or attribute from the context will act as a data source for an UI element property. To exemplify the data binding mechanism, we create a component named Y_DATABINDING with a view named V_BIND and a window W_DEFAULT (Fig. 6.1). U. Gellert and A.D. Cristea, Web Dynpro ABAP for Practitioners, DOI 10.1007/978-3-642-11385-7_6, # Springer-Verlag Berlin Heidelberg 2010
67
68
6 Data Binding, Context Mapping and Interface Methods
Fig. 6.1 Structure of Y_DATABINDING component
In context view, we create a context node STUDENT with the same dictionary structure YSTR_PERSON (Fig. 6.2).
Fig. 6.2 Structure of STUDENT node
We create a WD component that reads the user inputs in the attributes FIRSTNAME, LASTNAME and DATEOFBIRTH. When the user presses the “SHOW” button, these data are shown by means of TextView UI Elements (Fig. 6.3).
VIEW V_BIND View controller
Data binding
Fig. 6.3 Example of data binding
6.1 Data Binding
69
We have many possibilities to make a data binding. For example, we can: (a) Create a “Container Form” for a context node (b) Use the Web Dynpro Wizard (c) Create data binding for each attribute (a) To create a “Container Form”, we add a Group UI element and then, by rightclicking, we choose from the contextual menu “Create Container Form” (Fig. 6.4).
Fig. 6.4 Creating container form
After this, we can choose which context node we use for data binding and which type of UI Element is associated to each attribute (Fig. 6.5).
Fig. 6.5 Data binding
70
6 Data Binding, Context Mapping and Interface Methods
As a result, the Framework generates for each context attribute an UI element InputField and a proper label, and makes the data binding between each UI element property (value) and the context attribute (Fig. 6.6).
Fig. 6.6 Data mapping among InputField UI Elements and the context attributes
To create a “Container Form”, we can use each UI Element of container type. (b) To create a data binding, we can use the Web Dynpro Wizard button (Fig. 6.7). In case we use the Form option, the Framework generates a transparentContainer UI element that contains the UI elements that we have to choose in the same way as we have shown at point (a).
Fig. 6.7 Using wizard to create a form and the proper data binding
(c) To manually define a data binding for each attribute, we have to insert the proper UI Element and create data binding between an UI element property and a context attribute. We insert 3 TextView UI Elements and 3 Labels UI Elements (Fig. 6.8).
Fig. 6.8 Layout structure
6.1 Data Binding
71
We have to create the data binding between each text property of the TextView UI Element and the proper context attribute (Fig. 6.9).
Binding button
Fig. 6.9 Data binding
We repeat this step until we make data binding among the text property of all the three UI Elements and the proper context attributes. Then, we insert a Button UI Element in the Group GRP_STUDENT_WRITE and add an action (Fig. 6.10).
Fig. 6.10 Inserting a button and adding an action
In this case, we don’t need to enter coding in the generated event handler method onactionshow. After creating an application for our component, we are ready to run it. The result is presented in Fig. 6.11. At runtime, the context attributes are empty. After the user enters values and pushes the SHOW button, the context attributes are populated with these values.
72
6 Data Binding, Context Mapping and Interface Methods
At design time, we realised a data binding among the TextView UI Elements and the same context attributes (Firstname, Lastname and Dateofbirth). This is the reason why these UI Elements show the values entered by the user in the InputFields UI elements.
Fig. 6.11 Running the application
6.2
Context Mapping
So far, we have used only context attributes that were defined in the view context. When we want to share data among different controllers, we have to define a context mapping. A context mapping can be an internal context mapping or an external context mapping. An internal mapping relationship can be defined between any pair of controllers within the same WD component, whereas the external mapping defines a mapping across the borders of a WD component.
6.2.1
Internal Context Mapping
As mentioned before, the mechanism for sharing data among different controllers within the same WD component is known as internal context mapping. For a better understanding of this mechanism, we create the same example from data binding, but in this case we create the two groups GRP_STUDENT_READ and GRP_STUDENT_WRITE, in different views. At runtime, we display the view V_VIEW1. When the user presses the “SHOW” button, we display the second view V_VIEW2. The WD component structure is presented in Fig. 6.12.
6.2 Context Mapping
73
Fig. 6.12 WD component structure
We cannot create the context node in the view context, because we need the values of this attributes not only in the view V_VIEW1, but in the view V_VIEW2 as well. In this case, we create the node STUDENT in the context of component controller. In this way, through context mapping, we can access the context of the component controller via a view controller. Context mapping doesn’t cause the duplication of data. The nodes in the view controllers only hold a reference to the mapping context node from the component controller (Fig. 6.13).
V_VIEW1 controller Component controller
V_VIEW2 controller
Fig. 6.13 Internal context mapping
We firstly create the context node of the component controller. After this, we make a context mapping between the context of the view V_VIEW1 and the context node of component controller. As a result, the entire context node STUDENT is mapped (Figs. 6.14 and 6.15). In the same way, we proceed to make a context mapping between the context of the view V_VIEW2 and the context of component controller. Consequently, we have to create the view layout for the views V_VIEW1, V_VIEW2 and the data binding. Data stored in the context of the component
74
6 Data Binding, Context Mapping and Interface Methods
Fig. 6.14 Context mapping
Fig. 6.15 The mapping result
controller can be used within a view if we have firstly made a context mapping. The schematic representation is presented in Fig. 6.16. V_VIEW1 Layout
V_VIEW1 controller Component controller
ViewContainerUIElement V_VIEW2 Layout
V_VIEW2 controller
Internal context mapping Data binding Fig. 6.16 Intern context mapping, data binding
6.2 Context Mapping
75
The lines between controllers symbolize the context mapping, and the lines between view controllers and the views layout symbolize the data binding. In the view V_VIEW1, we create the group GRP_STUDENT_WRITE and then we can use the view context to create a “Container Form”. Because we want to show both views in the same window, after the user presses the “SHOW” Button we use a ViewContainerUIElement (Fig. 6.17).
Fig. 6.17 View layout for V_VIEW1
In Fig. 6.18 we present the structure of the view V_VIEW2.
Fig. 6.18 View layout for V_VIEW2
We have to embed the view V_VIEW2 in the ViewContainerUIElement (Fig. 6.19).
Fig. 6.19 Embed view V_VIEW2
76
6 Data Binding, Context Mapping and Interface Methods
After creating an application, we can see the result. At runtime, the User Interface is the same as for the data binding (example – Fig. 6.11). The difference is the context mapping. In this case, the context is not defined in the view context, but in the context of the component controller, and can be accessed through context mapping. The data reside in the context node of the component controller context, and the context node of the views controller simply holds a reference to this.
6.2.2
External Context Mapping
External mapping is a cross-component mapping and can be directly mapping or reversely mapping. We can create an external context mapping if we have firstly declared a usage for the component that holds the respective context and the respective context node has been marked as interface. 6.2.2.1
Direct Mapping
As a briefly description of this kind of mapping, we can say that the external mapping of direct mapping type is a cross-component mapping in which the main component directly access the data (represented through the context structure) of the used component. For a better understanding of this type of mapping, we create the same example for the internal mapping, but in this case we create two WD components (Fig. 6.20). The component Y_EM_LAYOUT has two Views used to create the user inter-
Fig. 6.20 WD component structure
face. To hold the data entered by the user, we use the context node STUDENT. To be able to access this context node, we have to define a component usage. In WD, the component Y_EM_LAYOUT defines a usage of the component Y_EM_CONTEXT (Fig. 6.21). In real cases, a faceless component is useful if several components access the same set of data. This type of component can be used to create a model for a multicomponent application.
6.2 Context Mapping
77
We firstly create the context node in component controller of the component Y_EM_CONTEXT. We keep the same context node STUDENT, but in this case we create an interface node. If this node has not defined the interface type, we cannot access it from another component (Fig. 6.21).
Fig. 6.21 Context node structure
The component Y_EM_LAYOUT has two Views used to create the user interface. To hold the data entered by the user, we use the context node STUDENT. To be able to access this context node, we have to define a component usage. In WD, the component Y_EM_LAYOUT defines a usage of the component Y_EM_CONTEXT (Fig. 6.22).
Fig. 6.22 Defining a Usage in a component
78
6 Data Binding, Context Mapping and Interface Methods
After the usage is defined, we have to create a controller usage in the component controller. We need to use the component Y_EM_CONTEXT, the component use (named CONTEXT) and, hence, we need the INTERFACECONTROLLER (Fig. 6.23).
Fig. 6.23 Controller usage definition
The next step is to define a mapping. In this case, it is an external mapping, because the node we use to define the mapping is outside the component (Fig. 6.24).
Drag & Drop
Fig. 6.24 Defining an external mapping
As a result, the entire context node is mapped (Fig. 6.25).
Fig. 6.25 The mapping result
6.2 Context Mapping
79
In the Methods tab, we have to verify in the wddoinit( ) Hook Method if it is an instance of the used component. The coding from Listing 6.1 shows how we can verify this and how can be created in case it doesn’t exist. METHOD wddoinit . DATA: lr_cmp_usage TYPE REF TO if_wd_component_usage. lr_cmp_usage = wd_this->wd_cpuse_context( ). IF lr_cmp_usage->has_active_component( ) IS INITIAL. lr_cmp_usage->create_component( component_name = 'Y_EM_CONTEXT' ). ENDIF. ENDMETHOD.
Listing 6.1 Checking an instance of the used component
By using the method HAS_ACTIVE_COMPONENT of the IF_WD_COMPONENT_USAGE, we verify if the usage has an active component. If the component has already been initialized, the logic moves on; otherwise, we create an instance of the component by using the CREATE_COMPONENT method of the same interface. We must ensure that the external component has been instantiated before the interface controller is accessed. It is recommendable to create a usage for a component only in the moment we need it. In our little example, we have to create the usage in the wdDoInit Hook method, but, in case we use navigations plugs to navigate to a used component, it is recommendable to create the usage in the method used to fire the respective plug. Further, we can proceed as in the previous example: we create an internal mapping between the context node of the component controller and the context view of the views V_VIEW1 and V_VIEW2. After this, we can create the data binding. All these are schematically presented in Fig. 6.26. The line between WD components symbolizes the external direct context mapping, the lines between component controller and views controllers symbolize internal mapping, and the lines between view controllers and views layout symbolize the data binding. 6.2.2.2
Reverse Mapping
As a briefly description of this king of mapping, we can say that the external mapping of the reverse mapping type is a cross-component mapping in which the data (represented through the context structure) are put at our disposal by the main component. To realise the screen based on them, we use the interface view of the used component. For a better understanding of this type of mapping, we create the same example from direct mapping, where we change only the implementation part. We create two WD components, named Y_EM_CONTEXT_RM and Y_EM_LAYOUT_RM. The WD components structure is presented in Fig. 6.27. We define, in the component Y_EM_CONTEXT_RM, the context node STUDENT. This component has no view, because we embedded here the interface view
80
6 Data Binding, Context Mapping and Interface Methods
Y_EM_CONTEXT
Y_EM_LAYOUT V_VIEW1 Layout
V_VIEW1 controller
Component controller
ViewContainerUIElement V_VIEW2 Layout
V_VIEW2 controller
External mapping Internal mapping Data binding
Fig. 6.26 Schematic representation of an external direct mapping
Fig. 6.27 WD components structure
of the component Y_EM_LAYOUT_RM. The component Y_EM_LAYOUT_RM implements the user interface, making usage of the component Y_EM_CONTEXT_RM required to have access to the STUDENT node. Schematically, all these are presented in Fig. 6.28. We firstly create the context node in the component controller of the component Y_EM_CONTEXT_RM, by using the same context node STUDENT and interface node (Fig. 6.29).
6.2 Context Mapping
81
Y_EM_CONTEXT_RM Embedded Interface View
Y_EM_LAYOUT_RM V_VIEW1 controller
Component controller
Reverse mapping Internal mapping Data Binding
Fig. 6.28 Schematic representation of an external reverse mapping
Fig. 6.29 Interface node
The component Y_EM_LAYOUT_RM implements the user interface. In component controller, we create a node named STUDENT, with the same structure as the node STUDENT from the component controller of the component Y_EM_CONTEXT_RM (Fig. 6.30). After creating the node, we make an internal mapping, we create the user interface and make the data binding. Another solution is to copy the component Y_EM_LAYOUT and to make the proper changes. We can copy this component by right-clicking on the component name, and choose “Copy” from the contextual menu. We have to specify a name for the new component and a package where we want to save this component. We define a usage of the component Y_EM_CONTEXT_RM and create an external mapping, reverse mapping (Fig. 6.31).
82
6 Data Binding, Context Mapping and Interface Methods
Fig. 6.30 Interface node, Input element
Fig. 6.31 Context structure after usage and mapping
After entering the coding required to verify if it is an instance of the used component, we can save and activate. For the next step, we go back to the component Y_EM_CONTEXT_RM, where we have to define a usage for the component Y_EM_LAYOUT_RM, required to be able to embed its interface view (Fig. 6.32). After this, we can embed the interface view of the component for which we have defined only the usage. The Framework generates a corresponding interface view when we create a window. This interface can be embedded by other component, after the usage was defined. To embed the interface view or windows of the
6.3 Interface Methods
83
Fig. 6.32 Defining the usage
Y_EM_LAYOUT_RM component, we proceed in the same way as for embedding the views (Fig. 6.33).
Fig. 6.33 Embed operation
After entering the coding required to verify if an instance of the used component exists, we can save, activate and run the application. As an example of the reverse mapping usage, we can mention an ALV (SAP List Viewer) component we are going to use in Chapter 13.
6.3
Interface Methods
A method of a component controller can be marked as interface. In this way, it is possible to access it cross-component. This option is possible only for the methods applied to the component controllers. The methods that take place in Views or Windows can’t be marked as interface. For a better understanding of this kind of methods, we expand the previous example. In this example, after the user enters values and presses the “SHOW” button, the context attributes of the node STUDENT of the component
84
6 Data Binding, Context Mapping and Interface Methods
Y_EM_CONTEXT_RM are populated with these values. When we want to verify if the user have entered his first name, we have to define an interface method in the component controller of this component, a method that verifies if this attribute has a value or it is empty. For this purpose, we create the interface method named check_firstname() (Fig. 6.34).
Fig. 6.34 Marking a component controller method as interface
We create this method in the component Y_EM_CONTEXT_RM, because there is the context node where the values are transferred after the user presses the “SHOW” button. The coding presented in Listing 6.2 shows the coding implementation of this method. METHOD check_firstname . DATA lr_node TYPE REF TO if_wd_context_node. DATA ls_node TYPE if_componentcontroller=>element_student. DATA lv_firstname TYPE string. DATA lr_api_controller TYPE REF TO if_wd_controller. DATA lr_message_manager TYPE REF TO if_wd_message_manager. lr_node = wd_context->get_child_node( 'STUDENT' ). lr_node->get_attribute( EXPORTING name = 'FIRSTNAME' IMPORTING value = lv_firstname ). IF lv_firstname IS INITIAL. lr_api_controller ?= wd_this->wd_get_api( ). lr_message_manager = lr_api_controller->get_message_manager( ). lr_message_manager->report_error_message( message_text = 'The Field First Name is empty!'). ENDIF. ENDMETHOD.
Listing 6.2 Method check_firstname implementation
We read the value of the FIRSTNAME attribute into the local variable lv_firstname. After this, we verify if this attribute has a value or it is empty. In case this
6.3 Interface Methods
85
attribute is empty, we want to show a message with the string ‘The Field First name is empty!’. In this case, we have used the method REPORT_ERROR_MESSAGE of interface IF_WD_MESSAGE_MANAGER. To generate a message, we can use the Web Dynpro Code Wizard (Fig. 6.35).
Fig. 6.35 Usage of Web Dynpro Code Wizard
Is not recommended this art of programming, where the language-specific text elements are entered in the source text. In this case, we have used the easy way and not the best one. In the Chap. 10, we explain how we can create messages easy to use and translate, without more programming effort. After this method is implemented, we have to go back to the component Y_EM_LAYOUT_RM. When the user presses the SHOW button, we have to call the method check_firstname from the component use. If a method is marked as interface, we can cross-component access it. This means that we can call it from our onactionshow event handler method after we define a usage at the view level (Fig. 6.36).
Fig. 6.36 Usage definition
86
6 Data Binding, Context Mapping and Interface Methods
The coding from Listing 6.3 shows the implementation of onactionshow event handler method. METHOD onactionshow . DATA: lr_interfacecontroller TYPE REF TO yiwci__em_context_rm . lr_interfacecontroller = wd_this->wd_cpifc_context( ). lr_interfacecontroller->check_firstname( ). ENDMETHOD.
Listing 6.3 Method call in used controller
We can use Web Dynpro Code Wizard to generate this code (Fig. 6.37).
Fig. 6.37 Web Dynpro Code Wizard
In Fig. 6.38 we present the results.
Fig. 6.38 Runtime
Chapter 7
View Controller Methods
When it is dark enough, you can see the stars. Ralph Waldo Emerson
Abstract As we have seen in the previous chapters, in the Methods tab of a View we find various types of methods generated by the Framework, and we can also create our own methods. The purpose of this chapter is to present the role and the modality to use the various methods generated by the Framework and the modality to realize our own methods. Each view has exactly one view controller. The view controller can contain methods for data retrieval or for processing user inputs. As we have seen, each view has a Methods tab where we can create our own user-defined methods or we can find the methods generated by the Framework. In each Method tab of a View, we can find or create three types of methods: l
l
l
Event Handler: This kind of methods respond to actions or to events. An example of such a method is generated by the Framework when we define an inbound plug into a View. Another example is a method generated from the Framework when we create an action. Method: We can use this kind of methods to create User-defined instance methods. Another example is the Hook Methods generated by the Framework. Supply Function: When we create a node and define a supply function for it, the Framework generates a corresponding supply function method used to populate with data a context node.
7.1
Hook Methods
These methods cannot be deleted and represent the interface between the Framework and our application. The Hook Methods are called in a specific sequence according to a phase model. After generation, these methods are empty, but can be filled with source codes in case we want to interfere in a certain step of this phase model. U. Gellert and A.D. Cristea, Web Dynpro ABAP for Practitioners, DOI 10.1007/978-3-642-11385-7_7, # Springer-Verlag Berlin Heidelberg 2010
87
88
7 View Controller Methods
Table 7.1 shows the Hook methods to be found in different controllers. Table 7.1 Hook methods Hook methods wddoinit( ) wddoexit( ) wddobeforenavigation( ) wddopostprocessing( ) wddomodifyview( ) wddoafteraction( ) wddobeforeaction( ) wddooncontextmenu( ) wddoapplicationstatechange() wddoonopen( ) wddoonclose( )
Component controller YES YES YES YES – – – – YES – –
View controller YES YES – – YES YES YES YES – – –
Window controller YES YES – – – – – – – YES YES
Custom controller YES YES – – – – – – – – –
As we can see, the Hook methods wdDoInit and wdDoExit are common to all the controllers. The Fig. 7.1 shows which Hook methods can be found in a view.
Fig. 7.1 Hook methods in a view
7.1.1
wdDoInit
This method can be considered the controller constructor. It is automatically called when the controller is initialized for the first time. We have many examples where we can use this method, for example: setting the initial values of a controller context, dynamically creation of a context node and attributes, filling context nodes. We can use this method instead of the supply function method (to populate with values a context node), only if we know that the context is filled only once and it’s not invalidated afterwards. We create a WD component that uses the wdDoInit Hook method to populate with values a context node. The component structure and the view layout are presented in Fig. 7.2.
7.1 Hook Methods
89
Fig. 7.2 WD component structure, view layout
In the context view, we create a context node named STUDENT, with the same structure as the data binding example – dictionary structure YSTR_PERSON, cardinality 1. . .1, singleton, without supply function (Fig. 7.3).
Fig. 7.3 Context structure
Using the wdDoInit Hook method, we populate with values this node (Listing 7.1). When calling the application for the first time, the wdDoInit Hook method fills the node STUDENT with all the elements set here (Fig. 7.4).
Listing 7.1 The wdDoInit Hook method
METHOD wddoinit . DATA lr_node TYPE REF TO if_wd_context_node. DATA ls_data TYPE if_v_view=>element_student. lr_node = wd_context->get_child_node( 'STUDENT' ). ls_data-firstname = 'Antonia Maria'. ls_data-lastname = 'Keller'. ls_data-dateofbirth = '19800306'. lr_node->set_static_attributes( ls_data ). ENDMETHOD.
We can use the wdDoInit Hook Method to dynamically create the context node STUDENT and to populate it with values (Listing 7.2).
90
7 View Controller Methods
Fig. 7.4 Runtime
METHOD wddoinit . DATA: lr_node TYPE REF TO if_wd_context_node, lr_node_info TYPE REF TO if_wd_context_node_info, lr_child_node_info TYPE REF TO if_wd_context_node_info. lr_node_info = wd_context->get_node_info( ). lr_child_node_info = lr_node_info->add_new_child_node( name = 'STUDENT' is_singleton = abap_true is_multiple = abap_false is_mandatory = abap_true static_element_type = 'YSTR_PERSON' ). lr_node = wd_context->get_child_node( 'STUDENT' ). DATA ls_data TYPE ystr_person. ls_data-firstname = 'Antonia Maria'. ls_data-lastname = 'Keller'. ls_data-dateofbirth = '19800306'. lr_node->bind_structure( EXPORTING new_item = ls_data ). ENDMETHOD.
Listing 7.2 The wdDoInit Hook method
To dynamically create the context node “STUDENT”, we have used the method ADD_NEW_CHILD_NODE of the IF_WD_CONTEXT_NODE_INFO interface that creates an Info Object and adds it as a Lower-Level Node for the CONTEXT root node. The method CREATE_NODEINFO_FROM_STRUCT of the CL_ WD_DYNAMIC_TOOL class is obsolete and that’s why it is recommendable to use the if_wd_context_node_info->add_new_child_node. ADD_NEW_CHILD_NODE have many import parameters of which, for the scope of our example, we have used: l l
l
l
NAME of STRING type – the name of the generated context node IS_SINGLETON of ABAP_BOOL type, default value ABAP_FALSE – sets the property node SYNGLETON. In our example, the node STUDENT has to be singleton, and that’s why we have set this value ABAP_TRUE IS_MULTIPLE of ABAP_BOOL type, default value ABAP_TRUE – sets the property node CARDINALITY. In our example, the node STUDENT has the cardinality 1. . .1, and that’s why we have set this value ABAP_FALSE IS_MANDATORY of ABAP_BOOL type, default value ABAP_FALSE - sets the same property node CARDINALITY. We need the ABAP_TRUE value because the context node must have exactly one context element at runtime
7.1 Hook Methods l
91
STATIC_ELEMENT_TYPE of STRING type – we can use it to define the DICTIONARY_STRUCTURE property for our context node. Same as the case when this node is created at the design time, we can use the name of the development objects created in the ABAP Dictionary as Structure or Views
7.1.2
wdDoExit
This method can be considered the controller destructor. It is automatically called when exiting the controller, and can be used for executing closing statements. In the ABAP Dictionary, we have defined a lock for the database table YPERSON. We can use wdDoExit Hook method to release a lock that has been set for this table to synchronize the access of several WD applications to the same data. To do this, we have to use the generated DEQUEUE_EYPERSON Function Module (Listing 7.3). METHOD wddoexit . DATA lv_id_candidate TYPE yperson-id_person. DATA lr_node TYPE REF TO if_wd_context_node. DATA ls_data TYPE wd_this->element_candidate. lr_node = wd_context->get_child_node( 'CANDIDATE' ). lr_node->get_attribute( EXPORTING name = 'ID_PERSON' IMPORTING value = lv_id_candidate ). CALL FUNCTION 'DEQUEUE_EYPERSON' EXPORTING id_person = lv_id_candidate. ENDMETHOD.
Listing 7.3 The wdDoExit Hook method
Here we have called the Function Module directly from our WD method, but we can create a method in a class used as model for the WD component. If we don’t call the corresponding DEQUEUE_EYPERSON Function Module to release the database record that was locked with the EQUEUE_EYPERSON Function Module, this lock is generally removed at the end of the transaction.
7.1.3
wdDoModifyView
This method is mostly used in the dynamic programming, it is a method used for modifying the view before rendering. For the dynamically programming of the UI elements, we have many classes and methods that help us as application developer to dynamically modify a view. To show this, we create an example, a WD component, where we use this Hook method to dynamically create an InputField, a Label, a TextView and a LinkToAction UI
92
7 View Controller Methods
element. The WD component structure and the context node are presented in Fig. 7.5.
Fig. 7.5 WD component structure and context node
For the scope of this example, we import in the MIMEs (Multipurpose Internet Mail Extensions) folder an image: next.JPG that we use for the linkToAction UI element. To import a file in this folder, we right-click on the WD component name and, from the contextual menu, we choose Create ! Mime Object ! Import. The context node PERSON has the Cardinality 1. . .1, Singleton. Its attributes are NAME and GREETING, of string type. We can almost use the same example as for our first exercise. In this case, we create at design time only the UI element Group, the other UI elements being dynamically created by using the wdDoModifyView Hook method. The view layout is presented in Fig. 7.6.
Fig. 7.6 View layout
Listing 7.4 shows the content of the wdDoModifyView Hook method By using the FIRST_TIME parameter of WDY_BOOLEAN type, we check if wdDoModifyView is called for the first time. In case this parameter is ABAP_ TRUE (first time), we create a label UI Element: lr_label = cl_wd_label=>new_label( id = ‘NAME_LBL’ label_for = ‘NAME’ text = ‘NAME’). To do this, we use the method new_label of the cl_wd_label class interface (Fig. 7.7).
7.1 Hook Methods
93
METHOD wddomodifyview . DATA lv_bind_name TYPE string. DATA lv_bind_greeting TYPE string. DATA lr_link_to_action TYPE REF TO cl_wd_link_to_action. DATA lr_container TYPE REF TO cl_wd_group. DATA lr_flow_data TYPE REF TO cl_wd_flow_data. DATA lr_input_field TYPE REF TO cl_wd_input_field. DATA lr_text_view TYPE REF TO cl_wd_text_view. DATA lr_label TYPE REF TO cl_wd_label. IF first_time EQ abap_true.
lr_label = cl_wd_label=>new_label( id = 'NAME_LBL' label_for = 'NAME' text = 'NAME' ). lr_flow_data = cl_wd_flow_data=>new_flow_data( element = lr_label ). lr_container ?= view->get_element( 'GRP' ). lr_container->add_child( lr_label ). lv_bind_name = 'PERSON.NAME'. lr_input_field = cl_wd_input_field=>new_input_field( id = 'NAME' bind_value = lv_bind_name ). lr_flow_data = cl_wd_flow_data=>new_flow_data( element = lr_input_field ). lr_container->add_child( lr_input_field ). lr_link_to_action = cl_wd_link_to_action=>new_link_to_action( id = 'LTA_LINKTOACTION' on_action = 'NEXT' image_source = 'NEXT.JPG' ). lr_flow_data = cl_wd_flow_data=>new_flow_data( element = lr_link_to_action ). lr_container->add_child( lr_link_to_action ). lv_bind_greeting = 'PERSON.GREETING'. lr_text_view = cl_wd_text_view=>new_text_view( id = 'TXV_NAME' bind_text = lv_bind_greeting ). lr_flow_data = cl_wd_flow_data=>new_flow_data( element = lr_text_view ). lr_container->add_child( lr_text_view ). ENDIF. ENDMETHOD.
Listing 7.4 The WdDoModifyView Hook method
The new_label method has many mandatory and optional parameters. (Fig. 7.8) We have used label_for, text and ID to set the main properties of the Label UI element. The text parameter helps us to set the label text. The Label_for parameter specifies the UI element for which this label is. To embedding the UI elements into the layout, we need to specify the arrangement of these elements. For this, we have used the FlowLayout layout: lr_flow_data = cl_wd_flow_data=>new_flow_data( element = lr_label). The UI Element Group has the same layout.
94
7 View Controller Methods
Fig. 7.7 Class interface CL_WD_LABEL
Fig. 7.8 Parameters for the new_label method
After creating the UI element and setting the layout, we have to attach them to the ROOTCONTAINERUIELEMENT or to another container. In our case, we have attached our new created label to the UI element Group with the GRP ID. lr_container ?= view->get_element( ‘GRP’ ). lr_container->add_child( lr_label ). We have used the method add_child( ) that enabled us to do this. After this, we create an InputField UI element: lr_input_field = cl_wd_input_field=>new_input_field( id = ’NAME’ bind_value = lv_bind_name). We use the new_input_field method from the cl_wd_input_field class interface. The bind_value parameter represents the value property for the UI element property. In this case, we dynamically create a data binding for this property to the
7.1 Hook Methods
95
context node PERSON, attribute NAME. Until now, we have seen how we can create a data binding at the design time. In this case, we can’t create a data binding at design time, because this UI element doesn’t exist at the design time; it is dynamically created at runtime. To dynamically create a data binding of the property bind_value with the NAME attribute, we have to specify the absolute path of this attribute. lv_bind_name = ‘PERSON.NAME’. In the next step, we dynamically create a LinkToAction UI element: lr_link_to_action = cl_wd_link_to_action=>new_link_to_action( id = ‘LTA_LINKTOACTION’ on_action = ‘NEXT’ image_source = ‘NEXT.JPG’ ). We use the method new_link_to_action of the cl_wd_link_to_action class interface. This UI element has an event associated. We have used the parameter on_action to define the action that the Framework triggers when the user interacts with this UI element. For a linkToAction UI element, we can define a hypertext link or we can use an image instead a text. In our case, we have used the parameter image_source to specify the name of the image we want to use. Then, we specify the layout and we attach it to our UI element Group with the same GRP ID. At the end, we dynamically create a TextView UI element by using the new_ text_view method of the cl_wd_text_view class interface lr_text_view = cl_wd_text_view=>new_text_view( id = ’TXV_NAME’ bind_text = lv_bind_greeting). The data binding to the context attribute GREETING is dynamically created. After creating the UI element, we specify the layout and we attach it to our UI element Group with the same GRP ID. All we have to do now is to create an action named Next (Fig. 7.9). When the user presses the linkToAction UI element, the Framework triggers the event handler method onactionnext (Listing 7.5).
Fig. 7.9 Action Next
96
7 View Controller Methods METHOD onactionnext . DATA: lv_name TYPE string, lv_greeting TYPE string. DATA lr_node TYPE REF TO if_wd_context_node. DATA ls_data TYPE wd_this->element_person. lr_node = wd_context->get_child_node( 'PERSON' ). lr_node->get_attribute( EXPORTING name = 'NAME' IMPORTING value = lv_name ). CONCATENATE 'Welcome' lv_name INTO lv_greeting SEPARATED BY
space.
ls_data-greeting = lv_greeting. lr_node->set_static_attributes( ls_data ). ENDMETHOD.
Listing 7.5 The onactionnext event handler method
At runtime, we have (Fig. 7.10):
Fig. 7.10 Runtime
In case we want to set “required” the state property of the Input UI element, we need only an extra line code: lr_input_field = cl_wd_input_field=>new_input_field( id = ‘NAME’ state = cl_wd_input_field=>e_state-required bind_value = lv_bind_name). We use the state parameter to dynamically set the property with the same name of the InputField UI element. If we don’t use this optional parameter, the default value is set: CL_WD_INPUT_FIELD=>E_STATE-NORMAL. Tip WdDoModifyView should be used only for UI manipulation and not for dynamically creation of the context nodes and attributes.
7.1.4
wdDoBeforeAction
We can use this method to perform our own validation before an action is triggered. To exemplify this, we create a Web Dynpro component named Y_WDDOBEFOREACTION with a view named V_VIEW and a window W_DEFAULT.
7.1 Hook Methods
97
In the context view, we create the well-known context node named STUDENT, with the same dictionary structure YSTR_PERSON, cardinality 1. . .1, singleton, without supply function. Our scope is to check if the user enters values in all the inputFields UI elements bound to the attributes of the context node STUDENT. The View layout is presented in Fig. 7.11.
Fig. 7.11 The View layout
In the wdDoBeforeAction Hook method, we use the static method CHECK_ MANDATORY_ATTR_ON_VIEW of the CL_WD_DYNAMIC_TOOL class to check if the user had entered values in all the mandatory fields (the state property of the inputField UI elements is set required) (Listing 7.6).
METHOD wddobeforeaction . DATA lr_api_controller TYPE REF TO if_wd_view_controller. DATA lr_action TYPE REF TO if_wd_action.
lr_api_controller = wd_this->wd_get_api( ). lr_action = lr_api_controller->get_current_action( ). IF lr_action IS BOUND. CASE lr_action->name. WHEN ‘SAVE’. cl_wd_dynamic_tool=>check_mandatory_attr_on_view( view_controller = lr_api_controller ). ENDCASE. ENDIF. ENDMETHOD.
Listing 7.6 The wdDoBeforeAction Hook method
When the user presses the Save button, the Web Dynpro Framework firstly checks, by using the wdDoBeforeAction Hook method, if all the required fields are filled. In case the user doesn’t enter values in all these fields, all the operations that had to take place after pressing the Save button are finished and the user is informed about this, through error messages and by highlighting the UI elements that generated these messages. In this way, we don’t have to manually check each mandatory field.
98
7 View Controller Methods
At runtime we have (Fig. 7.12)
Fig. 7.12 Runtime
7.1.5
wdDoOnContextMenu
We can use this method to provide hierarchical context menus in web Dynpro Views. In our first example, we have already seen the default context menu displayed by the Web Dynpro Framework when the user presses right-click on an UI element. We can create a context menu at design time, by using the CONTEXT_MENUS root, or dynamically, by coding the wdDoOnContextMenu Hook method. To exemplify how we can use this method to dynamically create context menus, we use the example from the wdDoBeforeAction Hook method. In this case, we offer to the user the possibility to personalize the field he wants to be mandatory. He will be able to choose between his first name as mandatory field and his last name as mandatory field. When he chooses the first name as mandatory, we will mark the corresponding field with a red star, and when he chooses the last name, we will mark the corresponding field with a red star. In the default mode, the first name is set as mandatory. To create this example, we have to perform some modifications into the last application. In this case, we have to set dynamic the state properties of the two inputField UI elements, corresponding to first name and last name. To be able to do this, we have to create, in the context view, two extra context attributes of WDUI_STATE type, to bind these attributes with the corresponding properties (Fig. 7.13). In this way, at design time, the two inputField UI elements are not marked as mandatory, anyway. To set in the default mode the first name as mandatory, we use the wdDoInit Hook method we have just learnt about (Listing 7.7).
7.1 Hook Methods
99
Fig. 7.13 Context structure and data binding
Listing 7.7 Setting the initial values for our node DYNAMIC
METHOD wddoinit . DATA lr_node TYPE REF TO if_wd_context_node. DATA ls_data TYPE wd_this->element_dynamic. lr_node = wd_context->get_child_node( 'DYNAMIC' ). ls_data-first_name = cl_wd_input_field=>e_state-required. ls_data-last_name = cl_wd_input_field=>e_state-normal. lr_node->set_static_attributes( ls_data ). ENDMETHOD.
To offer to the end user the capability to dynamically choose what value he wants to be mandatory from the two optional values, we have to code the wdDoOnContextMenu Hook method (Listing 7.8). With the first data statement, we create a local reference to the CL_WD_MENU class and two local references to the CL_WD_MENU_ACTION_ITEM, required to dynamically create our menu, and two menu options of menuActionItem type. We need the two menu options to offer to the user the possibility to choose between options: set first name as mandatory or set last name as mandatory. With the second data statement, we create two local variables required to read from the context attributes the status properties corresponding to the two inputFields UI elements (firstname, lastname) and a local reference required to access our context node. Firstly, we create a context menu by using the static method new_menu of the cl_wd_menu class. By using the static method new_menu_action_item of the cl_wd_menu_action_ item class, we create the two menu options we need. From the parameters of this class, we have used: l l
l
id: To set the ID of the view element on_action: To associate the action that will be triggered when the user presses the respective option text: The text that will be displayed for the respective menu option
100
7 View Controller Methods METHOD wddooncontextmenu . DATA: lr_menu TYPE REF TO cl_wd_menu, lr_menu_item1 TYPE REF TO cl_wd_menu_action_item, lr_menu_item2 TYPE REF TO cl_wd_menu_action_item. DATA: lr_node TYPE REF TO if_wd_context_node, lv_first_name TYPE wdui_state, lv_last_name TYPE wdui_state. lr_node = wd_context->get_child_node( 'DYNAMIC' ). lr_node->get_attribute( EXPORTING name = 'FIRST_NAME' IMPORTING value = lv_first_name ). lr_node->get_attribute( EXPORTING name = 'LAST_NAME' IMPORTING value = lv_last_name ). lr_menu = cl_wd_menu=>new_menu( id = 'CONTEXT_MENU' ). IF lv_first_name = 01 AND lv_last_name = 00. lr_menu_item1 = cl_wd_menu_action_item=>new_menu_action_item( id = 'LAST_NAME' on_action = 'LN_MANDATORY' text = 'Set last name as mandatory' ). lr_menu_item2 = cl_wd_menu_action_item=>new_menu_action_item( id = 'FIRST_NAME' on_action = 'FN_MANDATORY' text = 'set first name as mandatory' enabled = abap_false ). ELSEIF lv_first_name = 00 AND lv_last_name = 01. lr_menu_item2 = cl_wd_menu_action_item=>new_menu_action_item( id = 'FIRST_NAME' on_action = 'FN_MANDATORY' text = 'set first name as mandatory' ). lr_menu_item1 = cl_wd_menu_action_item=>new_menu_action_item( id = 'LAST_NAME' on_action = 'LN_MANDATORY' text = 'Set last name as mandatory' enabled = abap_false ). ENDIF. lr_menu->add_item( the_item = lr_menu_item1 ). lr_menu->add_item( the_item = lr_menu_item2 ). menu = lr_menu. ENDMETHOD.
Listing 7.8 The wdDoOnContextMenu example l
enabled: To set if this option is active or inactive. In the default mode, this parameter is set ABAP_TRUE, respective enabled
The local variables used to pass the values of the two attributes (firstname and lastname) are of the same type as the attributes: WDUI_STATE. By doubleclicking on the TYPE, the forward navigation is open and we can see a data element with a Domain as an elementary type. This domain has two fixed values: 00 for Normal item and 01 for required. Before we effectively create the two menu options, we have to check which one of the two state proprieties is set required and which one is set normal. In case the firstname is required and lastname is normal, we create the two menu options with “Set last name as mandatory” active and “Set first name as mandatory” inactive. In case the firstname is normal and the lastname is required, we create the two menu
7.1 Hook Methods
101
options with “Set last name as mandatory” inactive and “Set first name as mandatory” active. Then, we add the two created menu options of menuActionItem type to our context menu and display the respective menu by using the wdDoOnContextMenu Hook method, returning the parameter named menu. In Fig. 7.14 we have already seen that, for our InputFields UI elements, we have set the properties: l l
contextMenuBehaviour: Provides, not inherits from the container contextMenuId: Set with the IDs of our context menu options
Fig. 7.14 Runtime
All we have to do now is to create the respective actions: FN_MANDATORY and LN_MANDATORY, actions that the Framework triggers when the user presses our menu action items. The onactionln_mandatory event handler method is presented in Listing 7.9.
Listing 7.9 Event handler method triggered for the menu option with LAST_NAME ID
method ONACTIONLN_MANDATORY . DATA lr_node TYPE REF TO if_wd_context_node. DATA ls_data TYPE wd_this->element_dynamic. lr_node = wd_context->get_child_node( 'DYNAMIC' ). ls_data-first_name = cl_wd_input_field=>e_state-normal. ls_data-last_name = cl_wd_input_field=>e_state-required. lr_node->set_static_attributes( ls_data ). endmethod.
In case the user chooses the last name as mandatory, we have to set required the property state of the corresponding UI element and normal the property state of the UI element corresponding to the first name (Fig. 7.14). The onactionfn_mandatory event handler method is presented in Listing 7.10. In case the user chooses the first name as mandatory, we have to set required the property state of the corresponding UI element and to set normal the property state of the UI element corresponding to the last name (Fig. 7.15).
102
7 View Controller Methods
Listing 7.10 Event handler method triggered for the menu option with FIRST_NAME ID
method ONACTIONFN_MANDATORY . DATA lr_node TYPE REF TO if_wd_context_node. DATA ls_data TYPE wd_this->element_dynamic. lr_node = wd_context->get_child_node( 'DYNAMIC' ). ls_data-first_name = cl_wd_input_field=>e_state-required. ls_data-last_name = cl_wd_input_field=>e_state-normal. lr_node->set_static_attributes( ls_data ). endmethod.
Fig. 7.15 Runtime
7.2
Supply Function Methods
We have used this type of methods every time we have assigned a supply function to a context node, every time we have populated the context attributes of the context nodes with initial values via supply function. When a controller is called, these methods are called first. We have seen that a supply function can be assigned to each context node of a controller (Fig. 7.16).
Fig. 7.16 Context node and supply function
The Framework generates a corresponding supply function method (Fig. 7.17). An alternative for the supply function methods can be the wdDoInit Hook method, if we know that the context is filled only once at initialization and it is not invalidated afterwards.
7.3 User-Defined Instance Methods
103
Fig. 7.17 Supply function
7.3
User-Defined Instance Methods
In the Methods tab, we can create our own user-defined methods with or without parameters. After creating a user-defined method, we can call it in the same controller, by using the wd_this self reference. In this case, we copy our example from the wdDoModifyView Hook method and we create two extra user-defined methods: l l
A method named GREETING that has two import parameters A method named PERFORM_VALLIDATION that has one import parameter
In the ONACTIONNEXT event handler method, we check whether the attribute NAME is initial, respective if the user didn’t enter his first name. In case of initial attribute, we call our own defined PERFORM_VALIDATION method. By using this method, we show an error message. In case this attribute is not empty, we call our own defined GREETING method to create a greeting for the end user. The Fig. 7.18 shows the user-defined GREETING method. As we can see, this method has defined an importing parameter named P_NAME of STRING type and an importing parameter named P_NODE of ref to if_wd_context_node type. The P_NAME parameter holds the value of the NAME attribute. The Fig. 7.19 shows the user-defined PERFORM_VALIDATION method. As we can see, this method has an importing parameter named P_ELEMENT, referable to the interface IF_WD_CONTEXT_ELEMENT. In this case, we have used the method REPORT_ATTRIBUTE_ERROR_MESSAGE of the interface IF_WD_MESSAGE_MANAGER to report a Web Dynpro error message to a context attribute. The Listing 7.11 shows the ONACTIONNEXT event handler method. As we can see, the local variable lv_name holds the value of the NAME attribute. If this attribute is empty, we have to show an error message. To do this, we use our own defined PERFORM_VALIDATION method.
104
7 View Controller Methods
Fig. 7.18 User-defined GREETING method
Fig. 7.19 User-defined PERFORM_VALIDATION method
wd_this->perform_validation(EXPORTING p_element = lr_element). If this attribute is not initial, we use its value as exporting parameter for our own defined method GREETING wd_this->greeting( EXPORTING p_name = lv_namep_node = lr_node).
7.4 Fire Methods
105
METHOD onactionnext . DATA lr_node TYPE REF TO if_wd_context_node. DATA ls_data TYPE wd_this->element_person. DATA lv_name TYPE string. DATA lr_element TYPE REF TO if_wd_context_element. lr_node = wd_context->get_child_node( 'PERSON' ). lr_element = lr_node->get_element( ). lr_node->get_attribute( EXPORTING name = 'NAME' IMPORTING value = lv_name ). IF lv_name IS INITIAL. wd_this->perform_validation( EXPORTING p_element = lr_element ). ELSE. wd_this->greeting( EXPORTING p_name = lv_name p_node = lr_node ). ENDIF. ENDMETHOD.
Listing 7.11 The onactionnext event handler method
At runtime, we have (Fig. 7.20)
Fig. 7.20 Runtime
7.4
Fire Methods
A Fire method is a special kind of method generated by the Framework when we define an outbound plug. We need inbound plugs and outbound plugs to define the navigation between two views. These plugs are the entry and the exit point for each view. We create an example, a WD component that has two Views. The WD component structure is presented in Fig. 7.21.
106
7 View Controller Methods
Fig. 7.21 WD component structure
In this case, we want to navigate from the view V_VIEW1 to the view V_VIEW2, when the Framework triggers an event handler method, respective when the user presses a button. In the COMPONENTCONTROLLER, we create a context node PERSON, Cardinality 1. . .1, Singleton and one attribute NAME of string type (Fig. 7.22).
Fig. 7.22 Context structure
The data stored in the context of the component controller are used within the two views V_VIEW1 and V_VIEW2, through context mapping. The view V_VIEW1 layout is presented in Fig. 7.23.
Fig. 7.23 View V_VIEW1 layout
The view V_VIEW2 layout is presented in Fig. 7.24.
7.4 Fire Methods
107
Fig. 7.24 View V_VIEW2 layout
When the user presses the Next button, we want to navigate from the view V_VIEW1 to the view V_VIEW2. The view V_VIEW1 will be replaced with the view V_VIEW2. This navigation is possible through a navigation link between the views, in the window (Fig. 7.25).
Window: W_DEFAULT
Outbound Plug
Navigation Link
Inbound Plug
Fig. 7.25 Plugs and navigation
To set up navigation between our views, we must create an inbound plug for the view V_VIEW2 and an outbound plug for the V_VIEW1. In the Outbound Plug tab of the view V_VIEW1, we create an outbound plug named OP_TO_V_VIEW2 (Fig. 7.26).
Fig. 7.26 Outbound plug
In the Inbound plug tab of the view V_VIEW2, we create an inbound plug named IP_V_VIEW2 (Fig. 7.27).
108
7 View Controller Methods
Fig. 7.27 Inbound plug
When the user presses the Next button, the Framework triggers the event handler method onactionnext. Every time we create an outbound plug for a view, a special method is added to its interface. This method has the statement FIRE__PLG. To fire this method, we can use the Web Dynpro Code Wizard or select an outbound plug when creating an Action (Fig. 7.28). The event handler method has the following statement: METHOD onactionnext . wd_this->fire_op_to_v_view2_plg( ). ENDMETHOD.
Fig. 7.28 Creating an action
We use the self-reference WD_THIS of the view controller to fire the method FIRE_OP_TO_V_VIEW2_PLG that was added to this interface when we have created the outbound plug. All the views within a window can be connected to each other by using navigation links. To be able to create the navigation, we embed the views in the window and then we drag & drop the outbound plug to the inbound plug. We can also create navigation by right-clicking on the output plug name (Fig. 7.29).
7.5 Event Handler Methods
109
Fig. 7.29 Creating navigation link
At runtime, when the user interacts with the view V_VIEW1, his interaction will cause a request to the server. In response, the view V_VIEW1 will be replaced with the view V_VIEW2. This is possible through the navigation link defined between these views.
7.5
Event Handler Methods
An event handler method responds to actions or to events. We have used this type of methods every time we have assigned an action to an UI element. This kind of methods are special methods of a view controller that has the prefix ONACTION followed by the action name. As we have seen, the action is defined in the Action tab and the corresponding event handler method is generated by the Framework (Fig. 7.30).
Fig. 7.30 Action and event handler method
110
7 View Controller Methods
We can assign an action to an UI element that has an event, indifferent if this UI element is created dynamically or at the design time (Fig. 7.31).
Fig. 7.31 Action and UI element
Let’s create an example where we use an event handler method implemented to respond to events of inbound plugs! We have seen that the outbound plugs are the starting point of navigation, called in any method of the view controller by using the statement: wd_this->FIRE__PLG( ). This method allows also parameter transfer. wd_this->FIRE__PLG( PARAMETER = ‘value’). In this case, the PARAMETER has to be entered in the parameter table of the view controller. For a better understanding, we create the same example as for the fire methods, but in this case we show an error message when the user doesn’t enter a value in the inputField UI element. We will pass a reference to Message Manager from a view to another view, via an outbound parameter. In the View_1 we add in the parameter table, on the Outbound plug, a parameter named P_MM (Fig. 7.32).
Fig. 7.32 Defining the parameter for an Outbound Plug
7.5 Event Handler Methods
111
When the user presses the Next button, the Framework triggers the event handler method onactionnext (Listing 7.12). METHOD onactionnext . DATA: lr_api_controller TYPE REF TO if_wd_controller, lr_api_manager TYPE REF TO if_wd_message_manager. lr_api_controller ?= wd_this->wd_get_api( ). lr_message_manager = lr_api_controller->get_message_manager( ). wd_this->fire_op_to_v_view2_plg( p_mm = lr_message_manager ). ENDMETHOD.
Listing 7.12 Event handler method
The view V_VIEW2 has the inbound plug IP_V_VIEW2 (Fig. 7.33).
Fig. 7.33 Inbound plug
We don’t have the possibility to create a parameter for an Inbound Plug. In this case, we use the event handler method HANDLEIP_V_VIEW2 to read the value of the P_MM parameter. When an inbound plug is called, the handler method that is uniquely assigned to this inbound plug is called. This method is automatically generated in the view controller when the inbound plug is created. We find this method in the Methods tab of the view V_VIEW2 (Fig. 7.34).
Fig. 7.34 Event handler method
The value of the parameter P_MM is passed by the outbound plug OP_TO_V_ VIEW2. To be able to read the value of this parameter, we have to add the parameter P_MM to the signature of the event handler method assigned to the inbound plug, i.e. the HANDLEIP_V_VIEW2 event handler method (Fig. 7.35).
112
7 View Controller Methods
Fig. 7.35 Event handler method. Implementation
In this way, the value of the P_MM parameter is known by the event handler method and can be used to send a message in case the user doesn’t enter a value in the InputField UI element. Tip These kinds of event handler methods are not used to pass application data.
Chapter 8
Layout UI Elements
“In matters of style, swim with the current. In matters of principle, stand like a rock.” Thomas Jefferson
Abstract The following section details and describes the Layout of the UI elements. Here, we are going to present the various types of existent Layouts and the modality to use them, either in static or in dynamic variant. The layout helps us to manage the arrangement of the UI elements within their parent container. All the UI elements within a view are hierarchy arranged. The node ROOTUIELEMENTCONTAINER is the root of this hierarchy and all the UI elements within a view are children of this root container. It is of TransparentContainer type and has initially assigned to it the FlowLayout layout. In our first example, we have seen that we have the possibility to change it from TransparentContainer into another UI element, in case this one doesn’t have any children. Table 8.1 shows the layout UI elements that are available for arranging the UI elements in a view, and the corresponding LayoutData. The layout is the abstract base class of all the layout UI elements within Web Dynpro and has the runtime class CL_WD_LAYOUT. Table 8.1 Layout and LayoutData UI element Layout UI element LayoutData UI element FlowLayout FlowData GridLayout GridData RowLayout RowData MatrixLayout MatrixData
The layout data of an UI element are used to specify the position within a container and have the runtime class CL_WD_LAYOUT_DATA. U. Gellert and A.D. Cristea, Web Dynpro ABAP for Practitioners, DOI 10.1007/978-3-642-11385-7_8, # Springer-Verlag Berlin Heidelberg 2010
113
114
8.1
8 Layout UI Elements
FlowLayout
If we use the FlowLayout layout, all the UI elements are displayed in a line. By using the property WRAPPING of the container into which the UI elements are going to be integrated, we can manipulate the modality of putting these UI elements on screen. In case this property is ABAP_TRUE, the UI elements that don’t enter in the first line are arranged bellow, in another line, to automatically adapt to the client window. In case of ABAP_FALSE, the UI elements are not automatically adapted to the client window. For a better understanding, we create a Registration Form with three fields: first name, last name and date of birth. The WD component structure and the view layout are presented in Fig. 8.1.
Fig. 8.1 WD component structure and view layout
In View context, we create the same well-known STUDENT context node with the dictionary structure YSTR_PERSON. ROOTUIELEMENTCONTAINER and Group UI element are both UI elements of container type, which have the FlowLayout layout in the default mode (Fig. 8.2). Each UI element reference to a LayoutData object and every UI element inserted within a container must have the data layout that matches the respective container.
8.1 FlowLayout
Fig. 8.2 Layout and layout data
At runtime, we have: (Fig. 8.3)
Fig. 8.3 Runtime: wrapping ABAP_TRUE
115
116
8 Layout UI Elements
As we can see, the UI elements are arranged in a line. Because the attributes of STUDENT context node are empty, the InputField’s UI elements bound to these attributes are not shown. After the user presses the Save Button, we show all the data that the user has entered in the InputField UI elements. In this case, all the UI elements don’t enter in a line anymore, because the client window is too small for that. The elements that don’t enter in the first line are arranged below in another line, to automatically adapt to the client window. We can see that, for the layout data, we can set two properties: cellDesign that specifies the distance between rows and vGutter that specifies the additional distance to the left edge. The default of these values is cellDesign – padless (there is no distance between the row and the edges) and vGutter – none (no additional distance). In case the wrapping property is ABAP_FALSE, the UI elements that don’t enter in the first line are not arranged below in another line, they are not visible anymore (Fig. 8.4).
Fig. 8.4 Runtime: wrapping ABAP_FALSE
For a dynamic manipulation, we can use the runtime class CL_WD_FLOW_ DATA to embedding the UI elements into the container that has a FlowLayout layout. An example of using this class we have seen in the wdDoModifyView example.
8.2
GridLayout
If we use the GridLayout layout, all the UI elements are arranged in container in a tabular grid with a fixed number of columns. We can specify the number of columns in the grid by using the property colCount. The number of rows depends on the number of the UI elements added to the container. We create the same example, but in this case we use GridLayout layout for the Group container (Fig. 8.5).
8.2 GridLayout
117
Fig. 8.5 Group container: GridLayout
We arrange all the UI elements from the GRP Group UI element in two columns. In this case, at runtime we have: (Fig. 8.6).
Fig. 8.6 Runtime
As we can see, the number of columns is two and the number of rows is five. We want the Save button to remain alone in its row. To do this, we have to use an InvisibleElement (Fig. 8.7). This UI element is an invisible element on the screen and can be used to fill an empty cell in the GridLayout.
118
8 Layout UI Elements
Fig. 8.7 InvisibleElement and GridLayout
For a dynamic manipulation, we can use the runtime class CL_WD_GRID_ DATA to embedding the UI elements into the GRP container that has a GridLayout layout (Listing 8.1).
METHOD wddomodifyview. DATA lv_bind_attribute TYPE string. DATA lr_input_field TYPE REF TO cl_wd_input_field. DATA lr_container TYPE REF TO cl_wd_group. DATA lr_label TYPE REF TO cl_wd_label. DATA lr_grid_data TYPE REF TO cl_wd_grid_data. IF first_time EQ abap_true. lr_label = cl_wd_label=>new_label( id = 'FIRSTNAME_LABEL' label_for = 'FIRSTNAME' ) lr_grid_data = cl_wd_grid_data=>new_grid_data( element = lr_label ). lr_container ?= view->get_element( 'GRP' ). lr_container->add_child( index = 1 the_child = lr_label ). lv_bind_attribute = 'STUDENT.FIRSTNAME'. lr_input_field = cl_wd_input_field=>new_input_field( id = 'FIRSTNAME' bind_value = lv_bind_attribute ). lr_grid_data = cl_wd_grid_data=>new_grid_data( element = lr_input_field ). lr_container ?= view->get_element( 'GRP' ). lr_container->add_child( index = 2 the_child = lr_input_field ). ENDIF. ENDMETHOD.
Listing 8.1 Implementing wdDoModifyView( )
8.3 MatrixLayout
119
In this example, we dynamically created the first two UI elements: InputField for the user first name and the corresponding label. To embed these UI elements into the GRP container (GridLayout), we use the proper GridData layout.
8.3
MatrixLayout
If we use the MatrixLayout, all the UI elements from a container are arranged in columns. With MatrixLayout, we can produce a grid with a variable number of columns per row. Each UI element inserted in a container that has the MatrixLayout layout will contain either a MatrixData object or a MatrixHeadData object (Fig. 8.8).
Fig. 8.8 Layout and layout data
An UI element that has MatrixHeadData data layout starts a new row and the UI elements that have MatrixData data layout are shown in the same row, until an UI element is set MatrixHeadData and a new row is created (Fig. 8.9).
Fig. 8.9 UI elements arranged in a container by using a MatrixLayout layout
For a dynamic manipulation, we can use the runtime class CL_WD_MATRIX_ HEAD_DATA and CL_WD_MATRIX_DATA to embed the UI elements into the GRP container that has a MatrixLayout layout (Listing 8.2).
120
8 Layout UI Elements METHOD wddomodifyview. DATA lv_bind_attribute TYPE string. DATA lr_input_field TYPE REF TO cl_wd_input_field. DATA lr_container TYPE REF TO cl_wd_group. DATA lr_label TYPE REF TO cl_wd_label. DATA lr_matrix_head_data TYPE REF TO cl_wd_matrix_head_data. DATA lr_matrix_data TYPE REF TO cl_wd_matrix_data. IF first_time EQ abap_true. lr_label = cl_wd_label=>new_label( id = 'FIRSTNAME_LABEL' label_for = 'FIRSTNAME' ). lr_matrix_head_data = cl_wd_matrix_head_data=>new_matrix_head_data( element = lr_label ). lr_container ?= view->get_element( 'GRP' ). lr_container->add_child( index = 1 the_child = lr_label ). lv_bind_attribute = 'STUDENT.FIRSTNAME'. lr_input_field = cl_wd_input_field=>new_input_field( id = 'FIRSTNAME' bind_value = lv_bind_attribute ). lr_matrix_data = cl_wd_matrix_data=>new_matrix_data( element = lr_input_field ). lr_container ?= view->get_element( 'GRP' ). lr_container->add_child( index = 2 the_child = lr_input_field ). ENDIF. ENDMETHOD.
Listing 8.2 Implementing wdDoModifyView( )
8.4
RowLayout
If we use RowLayout, all the UI elements from a container are arranged into horizontal rows. Each UI element inserted in a container that has the RowLayout layout will contain either a RowData object or a RowHeadData object (Fig. 8.10).
Fig. 8.10 Layout and layout data
8.4 RowLayout
121
This kind of layout is helpful when we want to arrange our UI elements into horizontal rows, but where we don’t need a vertical alignment between the resulting columns – see Fig. 8.11.
Fig. 8.11 UI elements arranged in a container by using a RowLayout layout
For a dynamic manipulation, we can use the runtime class CL_WD_ROW_ HEAD_DATA and CL_WD_ROW_DATA to embed the UI elements into the GRP container that has a RowLayout layout (Listing 8.3). METHOD wddomodifyview. DATA lv_bind_attribute TYPE string. DATA lr_input_field TYPE REF TO cl_wd_input_field. DATA lr_container TYPE REF TO cl_wd_group. DATA lr_label TYPE REF TO cl_wd_label. DATA lr_row_head_data TYPE REF TO cl_wd_row_head_data. DATA lr_row_data TYPE REF TO cl_wd_row_data. IF first_time EQ abap_true. lr_label = cl_wd_label=>new_label( id = 'FIRSTNAME_LABEL' label_for = 'FIRSTNAME' ). lr_row_head_data = cl_wd_row_head_data=>new_row_head_data( element = lr_label ). lr_container ?= view->get_element( 'GRP' ). lr_container->add_child( index = 1 the_child = lr_label ). lv_bind_attribute = 'STUDENT.FIRSTNAME'. lr_input_field = cl_wd_input_field=>new_input_field( id = 'FIRSTNAME' bind_value = lv_bind_attribute ). lr_row_data = cl_wd_row_data=>new_row_data( element = lr_input_field ). lr_container ?= view->get_element( 'GRP' ). lr_container->add_child( index = 2 the_child = lr_input_field ). ENDIF. ENDMETHOD.
Listing 8.3 Implementing wdDoModifyView( )
Chapter 9
User Interface Elements (UI elements), Static and Dynamic Programming
“A goal is a dream with a deadline”. Napoleon Hill
Abstract The UI elements we can use in the Web Dynpro ABAP are divided in various categories. In this chapter, we are going to present some of the UI elements, included in the categories: action, selection, layout, complex, graphic and integration. Each UI element will be illustrated by an example, showing the modality of using it either in static or in dynamic variant. A UI element is a User Interface element we use to create a screen for the end user. The UI Elements are grouped in categories we can access via the View Layout, and each UI Element has some properties, as follows: l l
Common with other UI elements, inherited from superclasses Specific only for an UI element For example, the following properties are inherited:
l
l l
Tooltip: Shows a quick info text when the user passes the mouse pointer over the UI element Visible: Determined if an UI element is visible in the screen or not Enabled: Specified if the UI element is active or inactive
By using the Class Builder transaction SE24, we can see different classes along with their inheritances and attributes. For example, the class CL_WD_UIELEMENT is the super class of all the UI elements we use in Web Dynpro ABAP. Being super class, this class has CL_WD_VIEW_ELEMENT. Figure 9.1 presents the tooltip, visible and enable properties for an InputField UI element. Most of the UI elements properties can be bound to different context nodes or attributes. In this way, we can manipulate the UI elements via the data held in the context. Each bindable property of a UI element has a certain type. For example, the enabled property can be bound to an attribute of WDY_BOOLEAN type. When this U. Gellert and A.D. Cristea, Web Dynpro ABAP for Practitioners, DOI 10.1007/978-3-642-11385-7_9, # Springer-Verlag Berlin Heidelberg 2010
123
124
9 User Interface Elements (UI elements), Static and Dynamic Programming
Fig. 9.1 UI element properties
attribute is set ABAP_TRUE, the respective UI element is active. When this attribute is set ABAP_FALSE, the respective UI element is inactive. The UI elements, along with the aggregations, determine the appearance and behaviour of the UI elements on the screen. The Web Dynpro UI elements are divided in categories. Hereunder, we present some of these categories.
9.1
Action
The UI elements that contain an action are included in this category. Some of these UI elements we have already used (Button, LinkToAction).
9.1.1
Timed Trigger
This UI element triggers automatically and periodically an event. To specify the periodicity, we have to use its delay property. As we have mentioned above, most of the UI element properties can be bound. Hereunder, we show a table with some of the TimedTrigger properties that can be bound and the attribute type in case the property is bindable (Table 9.1). Table 9.1 Some of TimedTrigger UI element properties Name Type Delay I Enabled WDY_BOOLEAN Visible WDUI_VISIBILITY Tooltip Text
Initial value 0 True Visible
We created a WD Component with the structure presented in Fig. 9.2.
Fig. 9.2 WD component structure
Bindable Yes Yes Yes Yes
9.1 Action
125
At every 5 s, we trigger an event that uses a Function Module to generate a random number under 1,000. In context view, we create a node named COUNTER, cardinality 1. . .1, Singleton that has an attribute COUNTER_TT of i type. The View layout is presented in Fig. 9.3.
Fig. 9.3 View layout
We have used an action named TRIGGER to specify the action to be triggered after the specified delay – 5 (Listing 9.1).
Listing 9.1 TimedTrigger action
METHOD onactiontrigger. DATA lr_node TYPE REF TO if_wd_context_node. DATA ls_data TYPE wd_this->element_counter. DATA lv_step TYPE i. lr_node = wd_context->get_child_node( 'COUNTER' ). CALL FUNCTION 'GENERAL_GET_RANDOM_INT' EXPORTING range = 1000 IMPORTING random = lv_step. ls_data-counter_tt = lv_step. lr_node->set_static_attributes( ls_data ). ENDMETHOD.
The Function Module GENERAL_GET_RANDOM_INT has an import parameter named RANGE of i type and an exporting parameter named RANDOM of i type. This function returns the random value with 0 ( RANDOM ( RANGE. At runtime, we have (Fig. 9.4).
Delay 5
Fig. 9.4 Runtime
126
9.1.1.1
9 User Interface Elements (UI elements), Static and Dynamic Programming
Dynamic Programming
RUNTIME CLASS: CL_WD_TIMED_TRIGGER As we have seen, by using the wdDoModifyView( ) Hook method we can dynamically create an UI element. The same properties, events and aggregations as in the View Designer are available. Hereunder, we present a table showing the correspondence between the view designer name and the runtime name, with the proper types, in case of dynamic programming of a TimedTrigger UI element (Table 9.2).
Table 9.2 Dynamic programming View designer name Runtime name Type Delay DELAY i Enabled ENABLED WDY_BOOLEAN Tooltip TOOLTIP WDY_MD_TRANSLATABLE_TEXT Visible VISIBLE WDUI_VISIBILITY None: CL_WD_TIMED_TRIGGER)E_VISIBLE-NONE Visible: CL_WD_TIMED_TRIGGER)E_VISIBLE-VISIBLE
The implementation of a dynamic TimedTrigger UI element contains the following statements (Listing 9.2). DATA lr_timed_trigger TYPE REF TO cl_wd_timed_trigger. lr_timed_trigger = cl_wd_timed_trigger=>new_timed_trigger( id = 'TIMED_TRIGGER' delay = 5 on_action = 'TRIGGER').
Listing 9.2 Dynamic creation of a TimedTrigger UI element
9.1.2
ButtonChoice
We can use this UI element to choose among the various options offered by the menu. Hereunder, we present a list with some of the ButtonChoice properties that can be bound, and the attribute type in case the property is bindable (Table 9.3).
Table 9.3 Some of the ButtonChoice UI element properties Name Type repeatSelectedAction WDY_BOOLEAN selectedActionItem STRING imageSource STRING
Initial value True
Bindable Yes Yes Yes
9.1 Action
127
We create a WD application, where we use the ButtonChoice UI element to offer to the end user a menu list with two options: power and divide. To realise these calculations, we have used the methods of the class CL_FOEV_ BUILTINS. As we can see in Fig. 9.5, this class has many calculation methods, from the PLUS method (that performs a simple addition) to functions, in order to obtain the Integer Part or Hyperbola Sinus.
Fig. 9.5 Class CL_FOEV_BUILTINS
The structure of the POWER method is presented in Fig. 9.6.
Fig. 9.6 Structure of the POWER method
128
9 User Interface Elements (UI elements), Static and Dynamic Programming
This method has two importing parameters, named IM_ARG1 and IM_ARG2, and an exporting parameter, named EX_RESULT, of float type. The method DIVIDE has the same parameters. For this scope, we create our context node named CALCULATE, with the context attributes ARG1 of f type, ARG2 of f type and RESULT of f type, required to perform the calculations and to hold the result. The WD component structure and the view context structure are presented in Fig. 9.7.
Fig. 9.7 WD component structure and view context structure
The View layout is presented in Fig. 9.8.
Fig. 9.8 View layout
In the ButtonChoice UI element, we insert two options: menuactionitem1 and menuactionitem2. For the two created options, we set actions (divide and power), and we use the hotkey property to offer to the end user the capability to press the respective key combination to trigger the associated event handler method. When the user interacts the first time with the ButtonChoice UI element, an action can be selected, and the Framework triggers the proper event handler
9.1 Action
129
method. The last selected action remains on the ButtonChoice UI element after the action has been executed. This behaviour is possible through the property repeatSelectedAction (Fig. 9.9).
The last selected action remains on the ButtonChoice UI element after the action has been executed
Fig. 9.9 Some of the ButtonChoice UI element properties
The Framework triggers the event handler method onactiondivide when the user clicks the respective choice option button or he presses the CTRL_D key combination. Listing 9.3 shows the coding of this method.
METHOD onactiondivide. DATA lr_oref TYPE REF TO cx_foev_error_in_function. DATA ls_calculate TYPE wd_this->element_calculate. DATA lv_arg1 LIKE ls_calculate-arg1. DATA lv_arg2 LIKE ls_calculate-arg2. DATA lv_result LIKE ls_calculate-result. wd_this->attribute_get(IMPORTING p_arg1 = lv_arg1 p_arg2 = lv_arg2). TRY. cl_foev_builtins=>divide( EXPORTING im_arg1 = lv_arg1 im_arg2 = lv_arg2 IMPORTING ex_result = lv_result ). CATCH cx_foev_error_in_function INTO lr_oref. ENDTRY. wd_this->attribute_set( EXPORTING p_result = lv_result ). ENDMETHOD.
Listing 9.3 The onactiondivide event handler method
As we can see, to read the context attributes ATR1 and ATR2, we use the user defined method named ATTRIBUTE_GET that has two exporting parameters (Fig. 9.10). To pass the result of the division calculation into the context attribute RESULT, we have used the user defined method ATTRIBUTE_SET that has an importing parameter (Fig. 9.11).
130
9 User Interface Elements (UI elements), Static and Dynamic Programming
Fig. 9.10 User defined method required to read the context attributes
Fig. 9.11 User defined method required to populate the RESULT attribute
The runtime structure is presented in Fig. 9.12.
Fig. 9.12 Runtime for the Divide operation
9.1 Action
131
To rise to power a number (number1 risen to number2), the Framework triggers the event handler method onactionpower (Listing 9.4).
METHOD onactionpower. ………….. TRY. cl_foev_builtins=>power( EXPORTING im_arg1 = lv_arg1 im_arg2 = lv_arg2 IMPORTING ex_result = lv_result). CATCH cx_foev_error_in_function INTO lr_oref. ENDTRY. ……………. ENDMETHOD.
Listing 9.4 The onactionpower event handler method
We have used the static method POWER, of the calculation class CL_FOEV_ BUILTINS, to perform the number1 risen to number2 operation. To read the context attributes ATR1 and ATR2, we call the same user defined method ATTRIBUTE_ GET; to pass the calculation result, we call the method ATTRIBUTE_SET. In this example, we have caught errors that can occur, but we didn’t display their message to the user. The way we can use try. . . endtry, the way we can raise, catch and display exceptions will be detailed described in Chap. 10.
9.1.2.1
Dynamic Programming
RUNTIME CLASS: CL_WD_BUTTON_CHOICE Hereunder, we present a table showing the correspondence between the view designer name and the runtime name, with the proper types, in case of dynamic programming of a ButtonChoice UI element (Table 9.4).
Table 9.4 Dynamic programming View designer name Runtime name repeatSelectedAction REPEAT_SELECTED_ACTION imageSource IMAGE_SOURCE selectedactionItem SELECTED_ACTION_ITEM
Type WDY_BOOLEAN STRING STRING
The implementation of a dynamic ButtonChoice UI element with one menu action item, named DIVIDE, contains the following statements (Listing 9.5):
132
9 User Interface Elements (UI elements), Static and Dynamic Programming METHOD wddomodifyview. DATA lr_button_choice TYPE REF TO cl_wd_button_choice. DATA lr_flow_data TYPE REF TO cl_wd_flow_data. DATA lr_container TYPE REF TO cl_wd_uielement_container. DATA lr_menu_action TYPE REF TO cl_wd_menu_action_item. IF first_time EQ abap_true. lr_container ?= view->get_element( 'ROOTUIELEMENTCONTAINER' ). lr_button_choice = cl_wd_button_choice=>new_button_choice( id = 'BTN_CHOICE' text = 'Choose' repeat_selected_action = abap_false ). lr_flow_data = cl_wd_flow_data=>new_flow_data( element = lr_button_choice ). lr_container->add_child( lr_button_choice ). lr_menu_action = cl_wd_menu_action_item=>new_menu_action_item( id = 'MENUACTIONITEM1' text = 'Divide' on_action = 'DIVIDE' hotkey = cl_wd_menu_action_item=>e_hotkey-ctrl_p ). lr_button_choice->add_choice( the_choice = lr_menu_action ). ENDIF. ENDMETHOD.
Listing 9.5 Dynamic creation of a ButtonChoice UI element
9.2
Selection
This category contains UI elements that have selection options. Hereunder, we present some of the UI Elements included in this category.
9.2.1
DropDownByKey
This UI element provides the end user with a dropdown list from where he can choose only one entry. We create a WD Component named Y_UI_DROPDOWNBYKEY with a view named V_VIEW and a window. We have many possibilities to populate with values the dropdown list. For example, we can use a Domain defined in the ABAP Dictionary, we can use the wdDoInit Hook method or a supply function method. For our example, we use Y_COUNTRY_DOMAIN, domain that holds all the names of EU member states. The View layout is presented in Fig. 9.13.
9.2 Selection
133
Fig. 9.13 View layout structure
As we have mentioned above, most of the UI element properties can be bound. Hereunder, we present a table with some of the DropDownByKey properties that can be bound, and the attribute type in case the property is bindable (Table 9.5).
Table 9.5 Some of the DropDownByKey UI element properties Name Type Initial value readOnly WDY_BOOLEAN False selectedKey STRING – textDirection WDUI_TEXT_DIRECTION Inherit State WDUI_STATE Normal
Bindable Yes Mandatory Yes Yes
The property selectedKey is mandatory; this means we have to realise data binding at this attribute. The context structure is presented in Fig. 9.14.
Fig. 9.14 Context structure
We have a context node with the cardinality 1. . .1 Singleton that has two attributes. The KEY attribute is of Y_DEFORDOMAIN type, defined in the ABAP Dictionary, and the RESULT attribute is of string type. We define a data binding between the KEY attribute and the selectedKey property of the DropDownByKey (Fig. 9.15).
Fig. 9.15 Data binding
134
9 User Interface Elements (UI elements), Static and Dynamic Programming
If the selectedKey property of the DropDownByKey UI Element is bound to this attribute, the values stored in the attribute KEY are displayed in the selection list. We use the attribute RESULT to show, in the textView UI Element, the capital of the first two EU countries, from the dropdown list. After the user chooses a value, the Framework triggers the event handler method onactionselect_country (Listing 9.6). METHOD onactionselect_country. DATA lr_node TYPE REF TO if_wd_context_node. DATA ls_data TYPE wd_this->element_dropdownbykey. DATA lv_value TYPE string. lr_node = wd_context->get_child_node( 'DROPDOWNBYKEY' ). lr_node->get_attribute( EXPORTING name = 'KEY' IMPORTING value = lv_value ). CASE lv_value. WHEN 'AT'. ls_data-result = 'Vienna'. WHEN 'BE'. ls_data-result = 'Brussels'. WHEN OTHERS. ls_data-result = 'Unknown'. ENDCASE. lr_node->set_static_attributes( ls_data ). ENDMETHOD.
Listing 9.6 Event handler method
At runtime, we have (Fig. 9.16):
Fig. 9.16 Runtime
9.2.1.1
Dynamic Programming
RUNTIME CLASS: CL_WD_DROPDOWN_BY_KEY Hereunder, we present a table showing the correspondence between the view designer name and the runtime name, with the proper types, in case of dynamic programming of a DropDownByKey UI element (Table 9.6).
9.2 Selection
135
Table 9.6 Dynamic programming View designer name Runtime name Type selectedKey SELECTED_KEY String textDirection TEXT_DIRECTION WDUI_TEXT_DIRECTION Inherit: CL_WD_DROPDOWN_BY_KEY)E_TEXT_DIRECTION-INHERIT Ltr: CL_WD_DROPDOWN_BY_KEY)E_TEXT_DIRECTION-LTR Rtl: CL_WD_DROPDOWN_BY_KEY)E_TEXT_DIRECTION-RTL State STATE WDUI_STATE Normal: CL_WD_DROPDOWN_BY_KEY)E_STATE-NORMAL Required: CL_WD_DROPDOWN_BY_KEY)E_STATE-REQUIRED
The implementation of a dynamic DropDownByKey UI element contains the following statements (Listing 9.7).
DATA lr_dropdown_by_key TYPE REF TO cl_wd_dropdown_by_key. DATA lv_bind_attribute TYPE string. lv_bind_attribute = 'DROPDOWNBYKEY.KEY'. lr_dropdown_by_key = cl_wd_dropdown_by_key=>new_dropdown_by_key ( id = 'DDK' bind_selected_key = lv_bind_attribute text_direction = cl_wd_dropdown_by_key=>e_text_direction-ltr on_select = 'SELECT_COUNTRY' ).
Listing 9.7 Dynamic creation of a DropDownByKey UI element
9.2.2
DropDownByIndex
This UI element provides the end user with a dropdown list from where he can choose only one entry. This UI element doesn’t differ from the DropDownByKey when displayed on the screen, the implementation being the only difference. We create the same WD Component; in this case, we use a dropDownByIndex UI element instead of the dropDownByKey. In Fig. 9.17, we show the context structure. In this case, we use a context node with the dictionary structure SHSVALSTR2, cardinality 0. . .n, Singleton.
Fig. 9.17 Context structure
The View Layout is presented in Fig. 9.18.
136
9 User Interface Elements (UI elements), Static and Dynamic Programming
Fig. 9.18 View Layout
Here under, we present a table with some of the DropDownByIndex properties that can be bound, and the attribute type in case the property is bindable (Table 9.7). Table 9.7 Some of DropDownByIndex UI element properties Name Type readOnly WDY_BOOLEAN Texts Translatable text State WDUI_STATE textDirection WDUI_TEXT_DIRECTION
Initial value False – Normal Inherit
Bindable Yes Mandatory Yes Yes
As we can see, the texts property is mandatory. If this property of the dropDownByIndex UI Element is bound to the VALUE attribute, the values stored in this attribute are displayed in the selection list. Listing 9.8 shows how we can populate the dropdown list with values via a supply function method. Listing 9.8 Supply function method
METHOD supply_dropdownbyindex. DATA: ls_country TYPE if_v_view=>element_dropdownbyindex, lt_country LIKE TABLE OF ls_country. ls_country-value = 'Austria'. ls_country-key = 'Vienna'. APPEND ls_country TO lt_country. ls_country-value = 'Belgium'. ls_country-key = 'Brussels'. APPEND ls_country TO lt_country. node->bind_table( new_items = lt_country set_initial_elements = abap_true ). ENDMETHOD.
At runtime, we have (Fig. 9.19):
Fig. 9.19 Runtime
9.2 Selection
9.2.2.1
137
Dynamic Programming
RUNTIME CLASS: CL_WD_DROPDOWN_BY_IDX Hereunder, we present a table showing the correspondence between the view designer name and the runtime name, with the proper types, in case of dynamic programming of a DropDownByIndex UI element (Table 9.8).
Table 9.8 Dynamic programming View designer name Runtime name Type Texts TEXTS WDY_MD_TRANSLATABLE_TEXT textDirection TEXT_DIRECTION WDUI_TEXT_DIRECTION Inherit: CL_WD_DROPDOWN_BY_IDX)E_TEXT_DIRECTION-INHERIT Ltr: CL_WD_DROPDOWN_BY_IDX)E_TEXT_DIRECTION-LTR Rtl: CL_WD_DROPDOWN_BY_IDX)E_TEXT_DIRECTION-RTL State STATE WDUI_STATE Normal: CL_WD_DROPDOWN_BY_IDX)E_STATE-NORMAL Required: CL_WD_DROPDOWN_BY_IDX)E_STATE-REQUIRED
The implementation of a dynamic DropDownByIndex UI element contains the following statements (Listing 9.9): DATA lr_dropdown_by_index TYPE REF TO cl_wd_dropdown_by_idx. DATA lv_bind_attribute TYPE string. lv_bind_attribute = 'DROPDOWNBYINDEX.VALUE'. lr_dropdown_by_index = cl_wd_dropdown_by_idx=>new_dropdown_by_idx( id = 'DDI' bind_texts = lv_bind_attribute text_direction = cl_wd_dropdown_by_idx=>e_text_direction-ltr on_select = 'SHOW').
Listing 9.9 Dynamic creation of a DropDownByIndex UI element
9.2.3
RadioButtonGroupByIndex
This UI Element includes some RadioButtons, allowing the user to select only one value. Similar to the DropDown lists, we have here RadioButtons grouped by key and by index. Indifferent of the type, they don’t differ when they are displayed on the screen, but only in the implementation part. We create the same WD Component as for the DropDownByIndex UI element; in this case, we change the DropDownByIndex UI element with the RadioButtonGroupByIndex. The view context has the same structure. We create a context node named RADIOBUTTONGROUP_I with the dictionary structure SHSVALSTR2, cardinality 0. . .n, Singleton.
138
9 User Interface Elements (UI elements), Static and Dynamic Programming
Hereunder, we present a table with some of the RadioButtonGroupByIndex properties that can be bound, and the attribute type in case the property is bindable (Table 9.9). Table 9.9 Some of the RadioButtonGroupByIndex UI element properties Name Type Initial value readOnly WDY_BOOLEAN False Texts Translatable text – colCount I 1 State WDUI_STATE Normal
Bindable Yes Mandatory Yes Yes
The View Layout is presented in Fig. 9.20.
Fig. 9.20 View Layout
We define the same data binding between the VALUE attribute and the texts property of the RadioButtonGroupByIndex. If this property of the RadioButtonGroupByIndex UI Element is bound to the VALUE attribute, the values stored in this attribute are displayed in columns and rows. To specify the number of columns in which the RadioButtonGroup elements are grouped, we can use the property colCount. In our case, we have set “2”. This property can be personalised by an administrator. Listing 9.10 shows how we can populate the RadioButtons with values via a supply function method (the same method as for the DropDownByIndex lists).
Listing 9.10 Supply function method
METHOD supply_radiobutton_i. DATA: ls_country TYPE wd_this->element_radiobuttongroup_i, lt_country LIKE TABLE OF ls_country. ls_country-value = 'Austria'. ls_country-key = 'Vienna'. APPEND ls_country TO lt_country. ls_country-value = 'Belgium'. ls_country-key = 'Brussels'. APPEND ls_country TO lt_country. node->bind_table( new_items = lt_country set_initial_elements = abap_true ). ENDMETHOD.
9.2 Selection
139
At runtime, we have (Fig. 9.21): Fig. 9.21 Runtime
For the RadioButtonGroupByKey UI element, we have the same concept as described for the DropDownByKey.
9.2.3.1
Dynamic Programming
RUNTIME CLASS: CL_WD_RADIOBUTTON_GROUP_BY_IDX Hereunder, we present a table showing the correspondence between the view designer name and the runtime name, with the proper types, in case of dynamic programming of a RadioButtonGroupByIndex UI element (Table 9.10). Table 9.10 Dynamic programming View designer name Runtime name Type colCount COL_COUNT I Texts TEXTS WDY_MD_TRANSLATABLE_TEXT State STATE WDUI_STATE Normal: CL_WD_RADIOBUTTON_GROUP_BY_IDX)E_STATE-NORMAL Required: CL_WD_RADIOBUTTON_GROUP_BY_IDX)E_STATE-REQUIRED
The implementation of a dynamic RadioButtonGroupByIndex UI element contains the following statements (Listing 9.11):
DATA lr_radiobutton_group_by_index TYPE REF TO cl_wd_radiobutton_group_by_idx. DATA lv_bind_attribute TYPE string. lv_bind_attribute = 'RADIOBUTTONGROUP_I.VALUE'. lr_radiobutton_group_by_index = cl_wd_radiobutton_group_by_idx=>new_radiobutton_group_by_idx( id = 'RDB_INDEX' bind_texts = lv_bind_attribute col_count = 2 on_select = 'SHOW’ ).
Listing 9.11 Dynamic creation of a RadioButtonGroupByIndex UI element
140
9.3
9 User Interface Elements (UI elements), Static and Dynamic Programming
Layout
This category has UI elements we use to form the layout. Hereunder, we present some of the UI Elements included in this category.
9.3.1
ViewContainerUIElement
This UI element is an area within a view that contains another view. It doesn’t have its own properties, but inherits properties from the abstract base class UIElement. We create a WD Component, a registration form with three views (Fig. 9.22). In the view V_VIEW, we insert two ViewContainerUIElement’s (VCU_1 and VCU_2) required to embed the V_STEP1 and V_STEP2 views. The context node is created in COMPONENTCONTROLLER because we have to share data among different view controllers: V_STEP1, V_STEP2, V_VIEW.
Fig. 9.22 WD component structure
The COMPONENTCONTROLLER context structure is presented in Fig. 9.23.
Fig. 9.23 Context structure
The node INFO has the cardinality 0. . .1, Singleton. The attributes NAME, EMAIL, CITY are of STRING type, and the attribute COUNTRY is of Y_DEFORDOMAIN type defined in the ABAP Dictionary, domain that holds all the EU member states.
9.3 Layout
141
At runtime, the view V_VIEW is the default view (e.g. the view that is first displayed when the window is called). The layout of this view is presented in Fig. 9.24.
Fig. 9.24 View V_VIEW layout
Because we want to display more views in the same time and in the same window, we are going to use ViewContainerUIElement. At runtime, when the screen is displayed for the first time, we want only the fields from V_VIEW view to be visible until the user presses the LinkToAction UI Element. This is the reason why we embed as default in VCU_1 and VCU_2 EMPTYVIEWs (Fig. 9.25). An EMPTYVIEW is a special type of view, automatically generated, that can be used to hide another view.
Fig. 9.25 Window structure
At runtime, we have (Fig. 9.26):
Fig. 9.26 Runtime
142
9 User Interface Elements (UI elements), Static and Dynamic Programming
As we can see, only the UI Elements from the default view V_VIEW are displayed, because the VCU_1 and VCU_2 have EMPTYVIEWs as default. All these are schematically shown in Fig. 9.27. Fig. 9.27 Embedding Views in Window
Component Y_UI_VIEWCONTAINERUIE Window W_DEFAULT View V_VIEW
VCU_1 EMPTYVIEW VCU_2 EMPTYVIEW
After the user presses the LinkToAction UI element, we want to show in the VCU_1 the view V_STEP1. To be able to do this, we define an outbound plug in the V_VIEW view (Fig. 9.28).
Fig. 9.28 Definition of an outbound plug in the view V_VIEW
In Fig. 9.29, we present the V_STEP1 layout.
Fig. 9.29 V_STEP1 view layout
9.3 Layout
143
To be able to show the view V_STEP1 content when the user presses the LinkToAction UI Element, we have to define an inbound plug in the view V_STEP1 (Fig. 9.30). Fig. 9.30 Definition of an Inbound Plug in the view V_STEP1
Now, we embed the view V_STEP1 in the ViewContainerUIElement VCU_1 and we create the navigation link (Fig. 9.31). Fig. 9.31 Window structure
When the user presses the LinkToAction UI element, the Framework triggers the event handler method onactionlta1. When we create an outbound plug for a view, a fire method is added to its interface. A fire method of our outbound plug op_to_v_ step1 is called with the statement: wd_this!fire_op_to_v_step1_plg( ). We have created a navigation link from OP_TO_V_STEP1 to IP_V_STEP1. When this method is fired, the view V_STEP1 is displayed. To integrate the fire method, we can use the Web Dynpro Code Wizard (Fig. 9.32).
Fig. 9.32 Calling the web Dynpro code wizard
144
9 User Interface Elements (UI elements), Static and Dynamic Programming
At runtime, we have (Fig. 9.33):
View V_STEP1
Fig. 9.33 Runtime
Hereunder, we have to display the view V_STEP2 when the user presses the LinkToAction UI element (ID = LTA_NEXT2). To do this, we define an outbound plug named OP_TO_V_STEP2 in the view V_STEP1, and we fire the generated method (Fig. 9.34).
Fig. 9.34 Outbound plug, event handler method
In Fig. 9.35, we present the V_STEP2 layout.
Fig. 9.35 V_STEP2 view layout
After this, we have to define an inbound plug named IP_V_STEP2, we embed the view V_STEP2 into the ViewContainerUIElement VCU_2 and we create the corresponding navigation link (Fig. 9.36).
9.3 Layout
145
Fig. 9.36 Window structure
Runtime structure is presented in Fig. 9.37.
View V_STEP2
Fig. 9.37 Runtime
9.3.1.1
Dynamic Programming
RUNTIME CLASS: CL_WD_VIEW_CONTAINER_UIELEMENT The implementation of a dynamic ViewContainerUIElement contains the following statements (Listing 9.12): data lr_vcu type ref to cl_wd_view_container_uielement. lr_vcu = cl_wd_view_container_uielement=>new_view_container_uielement ( id = 'VCU' ).
Listing 9.12 Dynamic programming of a ViewContainerUIElement
In this case, after dynamically creating the ViewContainerUIElement, we have to dynamically create the view embedding and the navigation links.
146
9.3.2
9 User Interface Elements (UI elements), Static and Dynamic Programming
TabStrip
This UI element allows us to display some tabs, and the user can toggle from a tab page to another. We create a WD Component, a registration form with the structure presented in Fig. 9.38.
Fig. 9.38 WD component structure
We create a TabStrip UI element and add two Tabs. To add tabs, we right-click on the tabStrip name and, from the contextual menu, we choose Insert Tab. When the user presses the Next button, we navigate to the next tab and we show the data entered by the user in the registration form of the first tab. The view Layout is presented in Fig. 9.39.
Fig. 9.39 View layout
9.3 Layout
147
Hereunder, we present a table with some of the tabStrip UI element properties that can be bound, and the attribute type in case the property is bindable (Table 9.11). Table 9.11 Some of TabStrip UI element properties Name Type selectedTab STRING tabAlignment WDUI_TAB_ALIGNMENT Width STRING
Initial value – Fast –
Bindable Yes Yes Yes
The property selectedTab of string type can be used to navigate from a tab to other one. This property set the name of the selected tab. We define a data binding between the selectedTab property and the attribute with the same name (string) defined in the node DYNAMIC in the view context. The node STUDENT has the dictionary structure YSTR_PERSON, cardinality 0. . .1, Singleton. The view context structure is presented in Fig. 9.40.
Fig. 9.40 Context structure
By using the wdDoInit Hook method, we populate the attribute SELECTEDTAB of the node DYNAMIC with the ID of the tab we want to be active at runtime – TAB_1 (Listing 9.13).
Listing 9.13 The wddoinit Hook method
METHOD wddoinit. DATA lr_node TYPE REF TO if_wd_context_node. DATA ls_data TYPE wd_this->element_dynamic. lr_node = wd_context->get_child_node( 'DYNAMIC' ). ls_data-selectedtab = 'TAB_1'. lr_node->set_static_attributes( ls_data ). ENDMETHOD.
When the user presses the Next Button, the Framework triggers the event handler method onactionnext (Listing 9.14). We set the selectedtab property with the value TAB_2, by selecting in this mode the TAB_2.
148
9 User Interface Elements (UI elements), Static and Dynamic Programming
Listing 9.14 Event handler method
METHOD onactionnext. DATA lr_node TYPE REF TO if_wd_context_node. DATA ls_data TYPE wd_this->element_dynamic. lr_node = wd_context->get_child_node( 'DYNAMIC' ). ls_data-selectedtab = 'TAB_2'. lr_node->set_static_attributes( ls_data ). ENDMETHOD.
The runtime structure is presented in Fig. 9.41.
Fig. 9.41 Runtime
9.3.2.1
Dynamic Programming
RUNTIME CLASS: CL_WD_TABSTRIP Hereunder, we present a table showing the correspondence between the view designer name and the runtime name, with the proper types, in case of dynamic programming of a TabStrip UI element (Table 9.12).
Table 9.12 Dynamic programming View designer name Runtime name selectedTab SELECTED_TAB Width WIDTH tabAlignment TAB_ALIGNMENT Exact: CL_WD_TABSTRIP)E_TAB_ALIGNMENT-EXACT Fast: CL_WD_TABSTRIP)E_TAB_ALIGNMENT-FAST
Type String String WDUI_TAB_ALIGNMENT
For the tabStrip UI element we have, as aggregation, the Tab element. Its runtime class is CL_WD_TAB. The implementation of a dynamic TabStrip UI element, with two Tabs, contains the following statements (Listing 9.15):
9.3 Layout
149
METHOD wddomodifyview. DATA lr_tabstrip TYPE REF TO cl_wd_tabstrip. DATA lr_flow_data TYPE REF TO cl_wd_flow_data. DATA lr_container TYPE REF TO cl_wd_uielement_container. DATA lr_tab1 TYPE REF TO cl_wd_tab. DATA lr_tab2 TYPE REF TO cl_wd_tab. IF first_time EQ abap_true. lr_container ?= view->get_element( 'ROOTUIELEMENTCONTAINER' ). lr_tabstrip = cl_wd_tabstrip=>new_tabstrip( id = 'TABSTRIP' selected_tab = 'TAB_1' on_select = 'SELECT' ). lr_flow_data = cl_wd_flow_data=>new_flow_data( element = lr_tabstrip ). lr_container->add_child( lr_tabstrip ). lr_tab1 = cl_wd_tab=>new_tab( id = 'TAB_1' ). lr_tab2 = cl_wd_tab=>new_tab( id = 'TAB_2' ). DATA lr_header1 TYPE REF TO cl_wd_caption. DATA lr_header2 TYPE REF TO cl_wd_caption. lr_header1 ?= cl_wd_caption=>new_caption( text = 'Tab1'). lr_header2 ?= cl_wd_caption=>new_caption( text = 'Tab2'). lr_tab1->set_header( lr_header1 ). lr_tabstrip->add_tab( the_tab = lr_tab1 ). lr_tab2->set_header( lr_header2 ). lr_tabstrip->add_tab( the_tab = lr_tab2 ). ENDIF. ENDMETHOD.
Listing 9.15 Dynamic programming of a TabStrip UI element
9.3.3
PageHeader
This UI element offers the possibility to create a header for a page. In the title content and the PageHeader Area, we can insert other UI elements. We create a WD component with the structure presented in Fig. 9.42.
Fig. 9.42 WD component structure
150
9 User Interface Elements (UI elements), Static and Dynamic Programming
We use the view V_VIEW as Master View. Here, we insert a PageHeader UI element that contains two LinkToAction UI elements, and in the PageHeader Area we insert a ViewContainerUIElement. When the user interacts with the LinkToAction UI elements, we show in the ViewContainerUIElement one of the two slave views V_COUNTRY or V_CANDIDATE. All these are schematically presented in Fig. 9.43.
Y_UI_PAGEHEADER
PageHeader Title Content
PageHeader Area
Fig. 9.43 Application structure
After the PageHeader UI element is inserted into the V_VIEW view, we can insert a PageHeader Title Content (Fig. 9.44 – right) and one or more PageHeader Area(s) (Fig. 9.44 – left).
Fig. 9.44 Inserting the title content and PageHeader area
In a PageHeaderArea, we can insert how many other UI elements we want. Here, we have chosen to insert only one UI element (ViewContainerUIELement). As design options, it has: Standard, Emphasized and transparent. For our example, we have the default design: Standard. To see on screen the other PageHeaderArea designs, we can choose values from the list, one by one, and see the result in the view designer, or we can run again the application and see the different changes. In the system, we can find two WD components where we can see the UI elements and the effect of changing certain properties on these UI elements. These components are WDR_TEST_EVENTS and WDR_TEST_UI_ELEMENTS. The V_VIEW has the layout presented in Fig. 9.45.
9.3 Layout
151
Fig. 9.45 V_VIEW view layout
Each view (V_CANDIDATE and V_COUNTRY) has a Table UI element where we show the data stored in our database table YPERSON and YEU_COUNTRIES. The resulted runtime is presented in Fig. 9.46. PageHeader Title content
PageHeader Area Fig. 9.46 Runtime
9.3.3.1
Dynamic Programming
RUNTIME CLASS: CL_WD_PAGE_HEADER Hereunder, we present a table showing the correspondence between the view designer name and the runtime name, with the proper types, in case of dynamic programming of a PageHeader UI element (Table 9.13). Table 9.13 Dynamic programming View designer name Runtime name Type Title TITLE WDY_MD_TRANSLATABLE_TEXT textDirection TEXT_DIRECTION WDUI_TEXT_DIRECTION CL_WD_PAGE_HEADER)E_TEXT_DIRECTION-INHERIT CL_WD_PAGE_HEADER)E_TEXT_DIRECTION-LTR CL_WD_PAGE_HEADER)E_TEXT_DIRECTION-RTL
152
9 User Interface Elements (UI elements), Static and Dynamic Programming
For the PageHeader UI element we have, as aggregation, the Area and the TitleContent elements. The Area runtime class is CL_WD_PAGE_HEADER_ AREA. The implementation of a dynamic PageHeader UI element (with pageHeader title) and a PageHeaderArea (with a textView UI element) contains the following statements (Listing 9.16): METHOD wddomodifyview. DATA lr_pageheader TYPE REF TO cl_wd_page_header. DATA lr_flow_data TYPE REF TO cl_wd_flow_data. DATA lr_container TYPE REF TO cl_wd_uielement_container. DATA lr_area TYPE REF TO cl_wd_page_header_area. IF first_time EQ abap_true. lr_container ?= view->get_element( 'ROOTUIELEMENTCONTAINER' ). lr_pageheader = cl_wd_page_header=>new_page_header( id = 'PH_PAGEHEADER' text_direction = cl_wd_page_header=>e_text_direction-ltr ). lr_pageheader->set_title( 'DYNAMIC PAGEHEADER' ). lr_flow_data = cl_wd_flow_data=>new_flow_data( element = lr_pageheader ). lr_container->add_child( lr_pageheader ). lr_area = cl_wd_page_header_area=>new_page_header_area( id = 'PAGEHEADAREA' design = cl_wd_page_header_area=>e_design-emphasized ). DATA lr_textview TYPE REF TO cl_wd_text_view. lr_textview = cl_wd_text_view=>new_text_view( id = 'TXT' text = 'PageHeaderArea' ). lr_area->set_content( the_content = lr_textview ). lr_pageheader->add_area( the_area = lr_area ). ENDIF. ENDMETHOD.
Listing 9.16 Dynamic programming of a PageHeader UI element
9.3.4
ContextualPanel
This UI element offers navigation functions. Its navigation list can have many levels. We create the same example as for the PageHeader, but, in this case, we use the two LinkToActionUIElements to create the content for a ContextualPanel UI element. In a contextualPanel UI element, we can insert three types of elements: FreeContextualArea, NavigationList and ViewSwitch. In our example, we have used two FreeContextualArea elements.
9.3 Layout
153
In a FreeContextualArea, we can insert a Content and a Header. We can set the header to be expandable or no. The Content is a zone where we can insert other UI elements we want to be displayed within the FreeContextualArea (Fig. 9.47).
Fig. 9.47 FreeContexualArea
The V_VIEW view Layout has the structure presented in Fig. 9.48.
Fig. 9.48 V_VIEW view Layout
At runtime, we have (Fig. 9.49):
Fig. 9.49 Runtime
154
9.3.4.1
9 User Interface Elements (UI elements), Static and Dynamic Programming
Dynamic Programming
RUNTIME CLASS: CL_WD_CONTEXTUAL_PANEL For the ContextualPanel UI element, we have, as aggregation, the items: FreeContextualArea, ViewSwitch and NavigationList elements. The FreeContextualArea runtime class is CL_WD_FREE_CONTEXTUAL_AREA. The implementation of a dynamic contextualPanel UI element, with a FreeContextualArea element that has a Content (linkToAction UI element) and a Header (expandableTitle element), contains the following statements (Listing 9.17):
METHOD wddomodifyview. DATA lr_flow_data TYPE REF TO cl_wd_flow_data. DATA lr_container TYPE REF TO cl_wd_uielement_container. DATA lr_contextualpanel TYPE REF TO cl_wd_contextual_panel. DATA lr_freecontextualarea TYPE REF TO cl_wd_free_contextual_area. DATA lr_linktoaction TYPE REF TO cl_wd_link_to_action. DATA lr_header TYPE REF TO cl_wd_expandable_title. IF first_time EQ abap_true. lr_container ?= view->get_element( 'ROOTUIELEMENTCONTAINER' ). lr_contextualpanel = cl_wd_contextual_panel=>new_contextual_panel( id = 'CP_CONTEXTUALPANEL' ). lr_freecontextualarea = cl_wd_free_contextual_area=>new_free_contextual_ar ea( id = 'FREECONTEXTUALAREA_1' ). lr_flow_data = cl_wd_flow_data=>new_flow_data( element = lr_contextualpanel ). lr_container->add_child( lr_contextualpanel ). lr_linktoaction = cl_wd_link_to_action=>new_link_to_action( id = 'CONTENT_1' on_action = 'SHOW_COUNTRIES' text = 'Show EU countries' ). lr_freecontextualarea->set_content( the_content = lr_linktoaction ). lr_header = cl_wd_expandable_title=>new_expandable_title( id = 'EXPANDABLETITLE_1' expandable = abap_true expanded = abap_true title = 'COUNTRY' ). lr_freecontextualarea->set_header( the_header = lr_header ). lr_contextualpanel->add_item( the_item = lr_freecontextualarea ). ENDIF. Listing 9.17 Dynamic programming of a contextualPanel UI element
9.3 Layout
9.3.5
155
Tray UI Element
As all the containers, this UI element includes a set of other UI Elements, but also provides additional functions. We create a WD Component with the structure presented in Fig. 9.50. Fig. 9.50 WD component structure
In the View Layout, we insert two Tray UI elements. The first element is used to show the candidate information, and the second Tray is used to show some details about the selected candidate. These details are: the country flag and the capital. In the MIMEs folder we import three pictures with the flags we have to display when the user chooses a competitor from that country. After the Tray UI element is inserted in the View Layout, we can insert a Menu (Fig. 9.51 – right) and, in each menu, we can insert a menu option (Fig. 9.51 – left).
Fig. 9.51 Tray menu
The menu options are: Menu, MenuActionItem, MenuCheckBox, MenuRadioButton and MenuSeparator. In our case, we have chosen the option MenuActionItem (Fig. 9.52).
156
9 User Interface Elements (UI elements), Static and Dynamic Programming
Fig. 9.52 Creating a menu element
The View Layout structure is presented in Fig. 9.53.
Fig. 9.53 View layout structure
The first Tray has two menu options, used to show the second Tray UI element or to hide it. As we have mentioned above, most of the UI element properties can be bound. Hereunder, we show a list with some of the Tray UI elements properties that can be bound, and the attribute type in case the property is bindable (Table 9.14).
Table 9.14 Some of the tray UI element properties Name Type Expanded WDY_BOOLEAN Design WDUI_TRAY_DESIGN hasContentPadding WDY_BOOLEAN scrollingMode WDUI_SCROLLING_MODE
Initial value True Transparent True None
Bindable Yes Yes Yes Yes
We want to manipulate the UI element via the data held in the context. Therefore, we create a context node named DYNAMIC, with three attributes: two attributes of WDY_BOOLEAN type (ENABLED_OPTION1, ENABLED_OPTION2) and one attribute named VISIBLE, of WDUI_VISIBILITY type. To show the concurrent information and the corresponding details, we have created a context node with
9.3 Layout
157
the dictionary structure YVIEW_CMPETITION, a database view defined in the ABAP Dictionary. The context structure is presented in Fig. 9.54. Fig. 9.54 Context structure
The context node DETAIL is populated via the supply function method SUPPLY_COMPETITION (Listing 9.18). METHOD supply_competition. DATA: lt_content TYPE TABLE OF yview_cmpetition. SELECT * FROM yview_cmpetition INTO TABLE lt_content. IF sy-subrc = 0. node->bind_table( new_items = lt_content ). ENDIF. ENDMETHOD.
Listing 9.18 Supply function method
To be able to manipulate the enabled properties of the menu options created in the first Tray UI elements, we define the following data binding: (Fig. 9.55)
Fig. 9.55 Data binding
158
9 User Interface Elements (UI elements), Static and Dynamic Programming
To be able to manipulate the visible property of the second Tray with the ID “TRAY_DETAIL”, we define a data binding between these properties and the context attribute VISIBLE: At initialisation, we want the second Tray to be hidden, the MENU_OPTION1 to be enabled and the MENU_OPTION2 to be not enabled. To realise this, we encode the wdDoInit Hook method (Listing 9.19).
Listing 9.19 The wddoinit Hook method
METHOD wddoinit. DATA lr_node TYPE REF TO if_wd_context_node. DATA ls_data TYPE wd_this->element_dynamic. lr_node = wd_context->get_child_node( 'DYNAMIC' ). ls_data-enabled_option1 = abap_true. ls_data-enabled_option2 = abap_false. ls_data-visible = cl_wd_tray=>e_visible-none. lr_node->set_static_attributes( ls_data ). ENDMETHOD.
When the user selects the first menu option “MENU_OPTION1”, the Framework triggers the event handler method onactionshow (Listing 9.20).
Listing 9.20 The onactionshow event handler method
METHOD onactionshow. DATA lr_node TYPE REF TO if_wd_context_node. DATA ls_data TYPE wd_this->element_dynamic. lr_node = wd_context->get_child_node( 'DYNAMIC' ). ls_data-enabled_option1 = abap_false. ls_data-enabled_option2 = abap_true. ls_data-visible = cl_wd_tray=>e_visible-visible. lr_node->set_static_attributes( ls_data ). ENDMETHOD.
When the user selects the second menu option MENListingU_OPTION2, the Framework triggers the event handler method onactionhide (Listing 9.21).
Listing 9.21 The onactionhide event handler method
METHOD onactionhide. DATA lr_node TYPE REF TO if_wd_context_node. DATA ls_data TYPE wd_this->element_dynamic. lr_node = wd_context->get_child_node( 'DYNAMIC' ). ls_data-enabled_option1 = abap_true. ls_data-enabled_option2 = abap_false. ls_data-visible = cl_wd_tray=>e_visible-none. lr_node->set_static_attributes( ls_data ). ENDMETHOD.
9.3 Layout
159
At runtime, we can choose to show or to hide the details about the competitor (Fig. 9.56).
Fig. 9.56 Runtime
9.3.6
MessageArea
This UI element represents the placeholder of the messages; it helps us to specify where they appear in the view. As we have seen, the messages are displayed by default in the upper part of the screen. The message location can be moved by adding a MessageArea UI element. We need only a MessageArea UI element per View layout. We create an example to filter an input from the end user. In case the user enters a combination of small and capital letters from A to Z or spaces, we show a message with the text “Your input is string” If not, we show a message “Your input is not string”. To show these messages, we use a MessageArea UI element. There are small programs used to test the regexes, which offer the possibility to test the regexes created before using them. Such a program is demo_ regex_toy. By using the transaction SA38 or SE38, we can run this program (Fig. 9.57). By using regexes, we can filter the values that the user enters in a Web Dynpro screen.
160
9 User Interface Elements (UI elements), Static and Dynamic Programming
Fig. 9.57 Regex toy screen
We begin our example with the creation of a component named Y_UI_MESSA GEAREA, with a View named V_VIEW. In the context view, we create a context attribute FIRSTNAME, of STRING type. The view layout is presented in Fig. 9.58.
Fig. 9.58 View Layout
9.3 Layout
161
As we can see, in this case we have entered a MessageArea UI element in the Group container. This is the place where all the messages will be displayed. When the user presses the button with the id “BTN”, the Framework triggers the event handler method onactioncheck (Listing 9.22).
METHOD onactioncheck. DATA: lv_firstname TYPE string, lv_pattern TYPE string. wd_context->get_attribute( EXPORTING name = 'FIRSTNAME' IMPORTING value = lv_firstname ). lv_pattern = '[a-zA-Z\s]*'. CHECK lv_firstname IS NOT INITIAL. DATA: lr_api_controller TYPE REF TO if_wd_controller, lr_message_manager TYPE REF TO if_wd_message_manager. lr_api_controller ?= wd_this->wd_get_api( ). lr_message_manager = lr_api_controller->get_message_manager( ). DATA: lt_message_parameters TYPE wdr_name_value_list, ls_message_parameter LIKE LINE OF lt_message_parameters. ls_message_parameter-name = 'first_name'. ls_message_parameter-value = lv_firstname. APPEND ls_message_parameter TO lt_message_parameters. IF cl_abap_matcher=>matches( pattern = lv_pattern text = lv_firstname ) = abap_true. lr_message_manager>report_message( message_text ='Your input &first_name is string' message_type = 0 params = lt_message_parameters ). ELSE. lr_message_manager>report_message( message_text = 'Your input &first_name is not string!' message_type = 2 params = lt_message_parameters ). endif. ENDMETHOD.
Listing 9.22 Checking the data entered by the user
By using the static method MATCHES of the CL_ABAP_MATCHER class, we check the value that the user enters in the inputField UI element. In case this value matches our condition specified in the local variable lv_pattern, we use the method REPORT_MESSAGE to display a message of information type. Otherwise, we use the same method to display an error message. Because we want to show to the user whether the value he entered in the input field is a string or not, we use a parameter required to integrate, in the string that he sees on the screen, the value he has just entered. For this purpose, we have used for the method report_message a parameter named “params”. By double-clicking on name of the method report_message, we navigate forward and we can see all the parameters that this method has and the type
162
9 User Interface Elements (UI elements), Static and Dynamic Programming
that the parameters should be. For the “parms” parameter, we need a variable of wdr_name_value_list type that is actually a table type with a structure of line type. From this structure, we have used the name (the parameter name, in our case “first_name”) and the value (the value with what we want to replace, at runtime, the parameter name “lv_firstname”). In Chap. 10, we will see more about the message manager and parameters, along with the modality we can display a message into a window, or the modality we can use the ABAP classes to create messages and exceptions. In Fig. 9.59, the messages are displayed by using the MesageArea UI element.
Fig. 9.59 Runtime with MessageArea UI element
Tip For more information about inputs validation and secure ABAP programming in general, please refer to the SAP Press book: “Sichere ABAP Programmierung” (Wiegenstein et al.)
9.3.6.1
Dynamic Programming
RUNTIME CLASS: CL_WD_MESSAGE_AREA Hereunder, we present a table showing the correspondence between the view designer name and the runtime name, with the proper types, in case of dynamic programming of a MessageArea UI element (Table 9.15).
Table 9.15 Dynamic programming View designer name Runtime name firstVisibleMessages FIRST_VISIBLE_MESSAGE historyvisible HISTORY_VISIBLE maxVisibleMessages MAX_VISIBLE_MESSAGES
Type I WDY_BOOLEAN I
The implementation of a dynamic MessageArea UI element contains the following statements (Listing 9.23):
9.4 Complex
163 data lr_messagearea type ref to cl_wd_message_area. lr_messagearea = cl_wd_message_area=>new_message_area( id = 'MESSAGE_AREA' HISTORY_VISIBLE = abap_true ).
Listing 9.23 The dynamic programming of a MessageArea UI element
9.4
Complex
This category contains complex UI elements as regards their structure and content. Hereunder, we present some of the UI Elements included in this category.
9.4.1
Table
By using this UI element, we can display data arranged in rows and columns. Table 9.16 shows some of the Table properties that can be bound, and the attribute type in case the property is bindable. Table 9.16 Some of the Table UI element properties Name Type selectionMode WDUI_TSMODE dataSource Context node rowSelectable WDY_BOOLEAN Design WDUI_TABLE_DESIGN gridMode WDUI_TABLE_GRID_MODE
Initial value Auto True Standard Both
Bindable Yes Mandatory Yes Yes Yes
In this exercise, we want to take data from an end user and to insert them into a table UI element, after the latest record. To do this, we create a WD component named Y_UI_TABLE that has a View named V_VIEW and a default window. In the context view, we need two context nodes: a context node required to hold the new record from the end user and a context node required to hold all the records. The context node structure is presented in Fig. 9.60.
Fig. 9.60 Context structure
164
9 User Interface Elements (UI elements), Static and Dynamic Programming
The context node REGISTRATION has the cardinality 1. . .1, Singleton. Its attributes are: NAME of STRING type, DATEOFBIRTH of YDATEOFBIRTH type, COUNTRY of Y_DEFORDOMAIN type and NO of I type. We use the attributes of this context node to hold every new record. The context node TABLE has the cardinality 0. . .n, Singleton, selection 0. . .1, supply function SUPPLY_PERSON and initialization lead selection is not automatically set. In this case, we want to manually set the lead selection. The context node attributes have the same name and data type as the context node REGISTRATION. We use the attributes of this context node to hold all the registrations. In the next step, we have to create the view layout. To insert a Table into our view layout, we can use two options: we can manually insert the table or we can use the Web Dynpro Wizard. In the beginning, we explain the first option. After inserting a Table UI element into our view, we have to create a data binding. When a table is bound to a context node by using a wizard, we don’t need to individually create each table column. We have only to select the context node and the Framework provides the available attributes. In this way, the value of the property DataSource (mandatory) of the Table UI element is bound to the context node TABLE (Fig. 9.61).
Fig. 9.61 Table UI element – Creating the binding
9.4 Complex
165
The Cell Editors of the Table Column describe the UI element used to display or edit the column content. As we can see, our columns are created by using textView UI elements. Each attribute represents a column in our table, and for each column we can choose an UI element. After this, the standard property to be bound depends on the chosen UI element. For example, for the TextView UI element, the property is text, and for the DropDownByKey, the name of the property to be bound is selectedKey (Fig. 9.62).
Fig. 9.62 Cell Editor of Table Column – Name of Property to be bound
The view layout is presented in Fig. 9.63. For each attribute for which the bind option is marked, the Framework generates a proper column. For example, for the attribute “NO”, the Framework has generated the column TBL_EXAMPLE_NO, for the attribute NAME, the Framework has generated the column TBL_EXAPLE_NAME, etc. The Table UI element offers the possibility to display as many rows as we need by using the property visibleRowCount (in our case, five). In the default mode, the property displayEmptyRows is set as ABAP_TRUE. In case we set this property as ABAP_FALSE, the rows that are empty in our table will not be on screen anymore. The second option to insert a Table UI element into our View Layout is to use the (Fig. 9.64). Web Dynpro Wizard In this case, the Wizard generates the Table UI element and we use the same procedure presented hereunder to create the data binding. After the user enters the new values (Name, Date of Birth and Country), we have to add these values at the end of the other records, in the table UI element. To be able to do this, we need an action.
166
9 User Interface Elements (UI elements), Static and Dynamic Programming
Fig. 9.63 View layout
Fig. 9.64 Web Dynpro wizard to insert a Table UI element into the view layout
For a table UI element, we can insert a Toolbar. We need a toolbar to be able to insert a ToolBarButton in this area (Fig. 9.65). We populate the node TABLE with two values, via the supply function method (Listing 9.24). The local variable lv_counter is used to create the record ID. After the node population, we use the SET_LEAD_SELECTION_INDEX method to set lead selection via index. As we can see, the index is set with the value of the lv_counter. In this way, it is selected the last value of the table.
9.4 Complex
167
Fig. 9.65 Inserting a ToolBarButton
METHOD supply_person. DATA: ls_table TYPE wd_this->element_table, lt_table LIKE TABLE OF ls_table, lv_counter TYPE i VALUE 1. ls_table-no = lv_counter. ls_table-name = 'Antonia Maria Crist'. ls_table-dateofbirth = '19800305'. ls_table-country = 'DE'. lv_counter = lv_counter + 1.
Listing 9.24 Supply function method
APPEND ls_table TO lt_table. ls_table-no = lv_counter. ls_table-name = 'Albu Alina'. ls_table-dateofbirth = '19800908'. ls_table-country = 'IT'. APPEND ls_table TO lt_table. node->bind_table( new_items = lt_table set_initial_elements = abap_true ). node->set_lead_selection_index( index = lv_counter ). ENDMETHOD.
168
9 User Interface Elements (UI elements), Static and Dynamic Programming
As we have mentioned above, if the “Initialization lead selection” for a node is “YES”, it is always selected the first element of this node. In this case, our context node has this property selected “NO”; we influence the selected element by using the set_lead_selection_index. To influence the lead selection, we have some methods, as following: l l l l
Set_lead_selection Move_first Move_previous Move_to
For our TABLE context node, we have set the selection cardinality 0. . .1, meaning that maximum one row can be selected if the node elements are displayed as a table. When the user presses the “Add record” button, the Framework triggers the event handler method onactionadd (Listing 9.25).
METHOD onactionadd. DATA: lr_node TYPE REF TO if_wd_context_node, lr_node1 TYPE REF TO if_wd_context_node, lr_element TYPE REF TO if_wd_context_element, lv_counter TYPE i, lv_dateofbirth TYPE ydateofbirth, lv_country TYPE y_defordomain, lv_name TYPE string, ls_registration TYPE wd_this->element_registration. lr_node = wd_context->get_child_node( 'REGISTRATION' ). lr_node->get_attribute( EXPORTING name = 'DATEOFBIRTH' IMPORTING value = lv_dateofbirth ). lr_node->get_attribute( EXPORTING name = 'NAME' IMPORTING value = lv_name ). lr_node->get_attribute( EXPORTING name = 'COUNTRY' IMPORTING value = lv_country ). lr_node1 = wd_context->get_child_node( 'TABLE' ). lr_node1->get_attribute( EXPORTING name = 'NO' IMPORTING value = lv_counter ). lv_counter = lv_counter + 1. ls_registration-no = lv_counter. ls_registration-dateofbirth = lv_dateofbirth. ls_registration-name = lv_name. ls_registration-country = lv_country. lr_node->set_static_attributes( ls_registration ). lr_element = lr_node->get_lead_selection( ). lr_element>get_static_attributes( IMPORTING static_attributes = ls_registration ). lr_node1 = wd_context->get_child_node( 'TABLE' ). lr_node1->bind_structure( EXPORTING new_item = ls_registration set_initial_elements = abap_false ). lr_node1->set_lead_selection_index( index = lv_counter ). ENDMETHOD.
Listing 9.25 Event handler method
9.4 Complex
169
We pass the value of the attribute NO of the TABLE context node in the local variable lv_counter. As we have mentioned above, we use this local variable to create the record ID. After each new record, we increase this value with 1. The user enters the values Name, Date of Birth and Country and we create his corresponding ID. The runtime structure is presented in Fig. 9.66.
Fig. 9.66 Runtime
Additionally, we can add a reset Button on the table toolbar. After the user adds the records, he can reset the fields Name, Date of birth and Country, to be able to add a new record. The “Reset” Toolbar Button, of the same ToolBarButton type, has associated an action named RESET. The Listing 9.26 shows the onactionreset event handler method. METHOD onactionreset. DATA: lr_node TYPE REF TO if_wd_context_node, ls_registration TYPE wd_this->element_registration. lr_node = wd_context->get_child_node('REGISTRATION' ). lr_node->bind_structure( EXPORTING new_item = ls_registration ). ENDMETHOD.
Listing 9.26 The onactionreset event handler method
The runtime structure is presented in Fig. 9.67.
170
9 User Interface Elements (UI elements), Static and Dynamic Programming
Fig. 9.67 Runtime
9.4.1.1
Dynamic Programming
RUNTIME CLASS: CL_WD_TABLE Hereunder, we present a table showing the correspondence between the view designer name and the runtime name, with the proper types, in case of dynamic programming of a Table UI element (Table 9.17). Table 9.17 Dynamic programming View designer name Runtime name dataSource DATA_SOURCE visibleRowCount VISIBLE_ROW_COUNT Design DESIGN Alternating: CL_WD_TABLE)E_DESIGN-ALTERNATING Standard: CL_WD_TABLE)E_DESIGN-STANDARD Transparent: CL_WD_TABLE)E_DESIGN-TRANSPARENT
Type Object VISIBLE_ROW_COUNT WDUI_TABLE_DESIGN
For the Table UI element, we have, as aggregation, the Table Column, Group Column, Header, Legend Popin, MasterColumn and Toolbar. The TableColumn element represents a column of a table, and has the CL_WD_TABLE_COLUMN runtime class. The table title is implemented by using a Caption element and has the CL_WD_CAPTION runtime class. The implementation of a dynamic Table UI element with table header, design alternating, three visible rows and a column, that has a TextView UI element as cell editor, contains the following statements (Listing 9.27).
9.4 Complex
171
METHOD wddomodifyview. DATA lr_table TYPE REF TO cl_wd_table. DATA lr_flow_data TYPE REF TO cl_wd_flow_data. DATA lr_container TYPE REF TO cl_wd_uielement_container. DATA lr_column_name TYPE REF TO cl_wd_table_column. DATA lr_text_view TYPE REF TO cl_wd_text_view. DATA lr_table_header TYPE REF TO cl_wd_caption. DATA lr_column_name_header TYPE REF TO cl_wd_caption. IF first_time EQ abap_true. lr_container ?= view->get_element( 'ROOTUIELEMENTCONTAINER' ). lr_table = cl_wd_table=>new_table( id = 'TBL_TABLE' bind_data_source = 'TABLE' design = cl_wd_table=>e_design-alternating visible_row_count = 3 ). lr_flow_data = cl_wd_flow_data=>new_flow_data( element = lr_table ). lr_container->add_child( lr_table ). lr_column_name = cl_wd_table_column=>new_table_column( id = 'TBL_EXAMPLE_NAME' ). lr_table_header ?= cl_wd_caption=>new_caption( text = 'Table UI elem ent - example'). lr_table->add_column( the_column = lr_column_name ). lr_table->set_header( lr_table_header ). lr_text_view = cl_wd_text_view=>new_text_view( id = 'TXV_NAME' bind_text = 'TABLE.NAME' ). lr_column_name_header ?= cl_wd_caption=>new_caption( text = 'Nam e'). lr_column_name>set_table_cell_editor( the_table_cell_editor = lr_text_view ). lr_column_name->set_header( lr_column_name_header ). ENDIF. ENDMETHOD.
Listing 9.27 Dynamic programming of a Table UI element
9.4.2
RoadMap
By using this UI element, we can display the steps required to complete a certain task. Hereunder, we show some of the roadMap properties that can be bound, and the attribute type in case the property is bindable (Table 9.18).
172
9 User Interface Elements (UI elements), Static and Dynamic Programming
Table 9.18 Some of roadMap UI element properties Name Type selectedStep STRING accessibilityDescription Translatable text startPointDesign WDUI_ROAD_MAP_EDGE_DESIGN endPointDesign WDUI_ROAD_MAP_EDGE_DESIGN
Initial value – – Standard Standard
Bindable Yes Yes Yes Yes
For the RoadMap example, we use the exercise from the ViewContainerUIElement, a little bit re-arranged. The WD component structure is presented in Fig. 9.68. Fig. 9.68 WD component structure
In this case, we replace the LinkToAction UI elements with two Buttons: Next and Back. These Buttons are inserted into the view V_VIEW, and the user can navigate from the first step to the end one, via the RoadMap. In this case, we used only a ViewContainerUIElement, and for each step we have a view. In the view V_VIEW, we insert a RoadMap UI element with three steps. To insert a step into a RoadMap UI Element, we right-click on the element and, from the contextual menu, we choose Insert Step (Fig. 9.69).
Fig. 9.69 RoadMap steps
9.4 Complex
173
The layout of the view V_VIEW is presented in Fig. 9.70.
Fig. 9.70 V_VIEW view layout
To be able to manipulate the RoadMap UI element and the Button via the data held in the context, we create, in the V_VIEW, a context node named DYNAMIC. This node has three attributes: l
l
l
SELECTEDSTEP, of STRING type, used to dynamically set the ID of the selected step ENABLED_NEXT, of WDY_BOOLEAN type, used to manipulate the enabled property of the NEXT button ENABLED_BACK, of WDY_BOOLEAN type, used to manipulate the enabled property of the BACK button (Fig. 9.71 – right)
To hold and show the data entered by the user, we have created, in the COM PONENTCONTROLLER context, a node named INFO (Fig. 9.71 – left). This context node has the same structure as presented in the ViewContainerUIElement example. The attributes are: NAME, EMAIL & CITY (of STRING type) and COUNTRY (of Y_DEFORDOMAIN type). We create a context mapping among this context node and the context views V_STEP1, V_STEP2 and V_STEP3.
Fig. 9.71 Context structure
174
9 User Interface Elements (UI elements), Static and Dynamic Programming
The V_STEP1 view layout has the structure presented in Fig. 9.72. Fig. 9.72 V_STEP1 view layout
The V_STEP2 view layout has the structure presented in Fig. 9.73.
Fig. 9.73 V_STEP2 view layout
The V_STEP3 view layout has the structure presented in Fig. 9.74.
Fig. 9.74 V_STEP3 view layout
The view “V_VIEW” is the default view – the firstly displayed one. In the ViewContainerUIElement, we embed all the three views V_STEP1, V_STEP2 and V_STEP3. The view V_STEP1 is, in this case, the default view. To be able to navigate among the views, we have to create inbound and outbound plugs. In the view V_VIEW, we create three outbound plugs: l l l
OP_TO_V_STEP1 required to navigate to the view V_STEP1 OP_TO_V_STEP2 required to navigate to the view V_STEP2 OP_TO_V_STEP3 required to navigate to the view V_STEP3
The view V_STEP1 has an inbound plug named IP_V_STEP1, the view V_STEP2 has an inbound plug named IP_V_STEP2 and the view V_STEP3 has an inbound plug named IP_V_STEP3.
9.4 Complex
175
The window structure is presented in Fig. 9.75. Fig. 9.75 Window structure
In the wdDoInit Hook method (V_VIEW), we dynamically set the attributes values for SELECTEDSTEP, ENABLED_NEXT and ENABLED_BACK (Listing 9.28).
Listing 9.28 The wdDoInit Hook method
METHOD wddoinit. DATA lr_node TYPE REF TO if_wd_context_node. DATA ls_data TYPE wd_this->element_dynamic. lr_node = wd_context->get_child_node( 'DYNAMIC' ). ls_data-enabled_next = abap_true. ls_data-enabled_back = abap_false. ls_data-selectedstep = 'STEP1'. lr_node->set_static_attributes( ls_data ). ENDMETHOD.
First time when the screen is rendered, we want the BACK Button to be not enabled, the NEXT Button to be enabled, and the STEP1 to be the active RoadMap step (Fig. 9.76).
Fig. 9.76 Runtime
176
9 User Interface Elements (UI elements), Static and Dynamic Programming
When the user presses the NEXT button, the Framework triggers the event handler method onactionnext (Listing 9.29). METHOD onactionnext. DATA lr_node TYPE REF TO if_wd_context_node. DATA ls_data TYPE wd_this->element_dynamic. DATA lv_selectedstep TYPE string. lr_node = wd_context->get_child_node( 'DYNAMIC' ). lr_node->get_attribute( EXPORTING name = 'SELECTEDSTEP' IMPORTING value = lv_selectedstep ). CASE lv_selectedstep. WHEN ‘STEP1’. ls_data-selectedstep = ‘STEP2’. ls_data-enabled_next = abap_true. ls_data-enabled_back = abap_true. wd_this->fire_op_to_v_step2_plg( ). WHEN ‘STEP2’. ls_data-selectedstep = ‘STEP3’. ls_data-enabled_next = abap_false. ls_data-enabled_back = abap_true. wd_this->fire_op_to_v_step3_plg( ). WHEN OTHERS. ls_data-enabled_next = abap_false. ls_data-enabled_back = abap_true. ENDCASE. lr_node->set_static_attributes( ls_data ). ENDMETHOD.
Listing 9.29 The onactionnext event handler method
As we can see, we make active the STEP2: ls_data-selectedstep = ‘STEP2’, we fire the method that helps us to navigate to the nextview V_STEP2 wd_this>fire_op_to_v_step2_plg( ) and we enable both buttons ls_data-enabled_next = abap_true. ls_data-enabled_back = abap_true (Fig. 9.77).
Fig. 9.77 Runtime
9.4 Complex
177
When the user presses again the NEXT button, we deactivate the NEXT button ls_data-enabled_next = abap_false we make active STEP3 ls_data-selectedstep = ‘STEP3’ and fire the method that helps us to navigate to the view V_STEP3 wd_this!fire_op_to_v_step3_plg( ), (Fig. 9.78) Fig. 9.78 Runtime
When the user presses the BACK button, the Framework triggers the event handler method onactionback (Listing 9.30). METHOD onactionback. DATA lr_node TYPE REF TO if_wd_context_node. DATA ls_data TYPE wd_this->element_dynamic. DATA lv_selectedstep TYPE string. lr_node = wd_context->get_child_node( ‘DYNAMIC’ ). lr_node->get_attribute( EXPORTING name = ‘SELECTEDSTEP’ IMPORTING value = lv_selectedstep ). CASE lv_selectedstep. WHEN ‘STEP3’. ls_data-selectedstep = ‘STEP2’. ls_data-enabled_next = abap_true. ls_data-enabled_back = abap_true. wd_this->fire_op_to_v_step2_plg( ). WHEN ‘STEP2’. ls_data-selectedstep = ‘STEP1’. ls_data-enabled_next = abap_true. ls_data-enabled_back = abap_false. wd_this->fire_op_to_v_step1_plg( ). WHEN OTHERS. ls_data-enabled_next = abap_true. ls_data-enabled_back = abap_false. ENDCASE. lr_node->set_static_attributes( ls_data ). ENDMETHOD.
Listing 9.30 The onactionback event handler method
178
9 User Interface Elements (UI elements), Static and Dynamic Programming
As we can see (Fig. 9.79), when the user presses the BACK button, we navigate back to the view V_STEP2 wd_this!fire_op_to_v_step2_plg( ). we activate both buttons ls_data-enabled_next = abap_true. ls_data-enabled_back = abap_true. we make active the step STEP2 ls_data-selectedstep = ‘STEP2’. wd_this!fire_op_to_v_step2_plg( ). Fig. 9.79 Runtime
When the user presses again the BACK Button (Fig. 9.80), we navigate back to the view V_STEP1 wd_this!fire_op_to_v_step1_plg( ). we deactivate the BACK button ls_data-enabled_back = abap_false. and make active the step STEP1 ls_data-selectedstep = ‘STEP1’.
Fig. 9.80 Runtime
9.4 Complex
9.4.2.1
179
Dynamic Programming
RUNTIME CLASS: CL_WD_ROAD_MAP Hereunder, we present a table showing the correspondence between the view designer name and the runtime name, with the proper types, in case of dynamic programming of a RoadMap UI element (Table 9.19). Table 9.19 Dynamic programming View designer name Runtime name Type selectedStep SELECTED_STEP String startPointDesign START_POINT_DESIGN WDUI_ROAD_MAP_EDGE_DESIGN CL_WD_ROAD_MAP)E_START_POINT_DESIGN-DISABLED CL_WD_ROAD_MAP)E_START_POINT_DESIGN-MORE CL_WD_ROAD_MAP)E_START_POINT_DESIGN-MORE_DISABLED CL_WD_ROAD_MAP)E_START_POINT_DESIGN-SELECTED CL_WD_ROAD_MAP)E_START_POINT_DESIGN-STANDARD
For the RoadMap UI element, we have, as aggregation, the Step: RoadMapStep or MultipleRoadMapStep. The RoadMapStep element represents a step in a RoadMap, and has the CL_WD_ROAD_MAP_STEP runtime class. The implementation of a dynamic RoadMap UI element with two Steps contains the following statements (Listing 9.31): METHOD wddomodifyview. DATA lr_container TYPE REF TO cl_wd_uielement_container. DATA lr_roadmap TYPE REF TO cl_wd_road_map. DATA lr_step1 TYPE REF TO cl_wd_road_map_step. DATA lr_step2 TYPE REF TO cl_wd_road_map_step. DATA lr_flow_data TYPE REF TO cl_wd_flow_data. IF first_time EQ abap_true. lr_container ?= view->get_element( 'ROOTUIELEMENTCONTAINER' ). lr_roadmap = cl_wd_road_map=>new_road_map( id = 'RM_ROADMAP' bind_selected_step = 'DYNAMIC.SELECTEDSTEP' start_point_design = cl_wd_road_map=>e_start_point_design-selected ). lr_flow_data = cl_wd_flow_data=>new_flow_data( element = lr_roadmap ). lr_container->add_child( lr_roadmap ). lr_step1 = cl_wd_road_map_step=>new_road_map_step( id = 'STEP1' description = 'STEP 1' name = '1' ). lr_roadmap->add_step( the_step = lr_step1 ). lr_step2 = cl_wd_road_map_step=>new_road_map_st id = 'STEP2' description = 'STEP 2' name = '2' ). lr_roadmap->add_step( the_step = lr_step2 ). ENDIF. ENDMETHOD.
Listing 9.31 Dynamic programming of a RoadMap UI element
180
9.4.3
9 User Interface Elements (UI elements), Static and Dynamic Programming
PhaseIndicator
Similar to the Road Map UI element, we can display then the steps in a wizard, by using the PhaseIndicator. Hereunder, we show some of the PhaseIndicator properties that can be bound, and the attribute type in case the property is bindable (Table 9.20). Table 9.20 Some of the PhaseIndicator UI element properties Name Type selectedPhase STRING accessibilityDescription Translatable text firstVisiblePhase STRING backgroundDesign WDUI_PHASE_IND_BGD_DESIGN
Initial value – – – Standard
Bindable Yes Yes Yes Yes
A Phase is a step into a PhaseIndicator that has bindable properties as, for example, enable and status. Table 9.21 presents some of these properties and how we can use the status property for a dynamic manipulation. Table 9.21 Some of the phase properties and the dynamic manipulation of the status Name Type Initial value Bindable Status WDUI_PHASE_STATUS Normal Yes Status: completed CL_WD_PHASE)E_STATUS-COMPLETED Status: normal CL_WD_PHASE)E_STATUS-NORMAL Status: unavailable CL_WD_PHASE)E_STATUS-UNAVAILABLE Status: warning CL_WD_PHASE)E_STATUS-WARNING
We create the same example as for the RoadMap, but, in this case, we use a PhaseIndicator UI element with three phases. The WD component structure is presented in Fig. 9.81.
Fig. 9.81 WD component structure
9.4 Complex
181
In this case, we have renamed the views V_STEP1, V_STEP2 and V_STEP3 as V_PHASE1, V_PHASE2 and V_PHASE3. The content of these views is the same. We can rename a view by right-clicking on the view name and, from the contextual menu, we choose rename. To insert a phase into a PhaseIndicator UI Element, we right-click on the element and, from the contextual menu, we choose Insert Phase (Fig. 9.82).
Fig. 9.82 Inserting Phase into a PhaseIndicator
For the first Phase, we have set the status property: completed. For the other two Phases (Phase2 and Phase3), we have dynamically set the status property, by using the two attributes named STATUS2 and STATUS3 of WDUI_PHASE_STATUS type. To manipulate the enabled property of the NEXT button, we use the same attribute ENABLED_NEXT of WDY_BOOLEAN type, and to manipulate the selected phase, we use the attribute SELECTEDPHASE of string type (Fig. 9.83 – right). The node INFO is defined in the COMPONENTCONTROLLER and has the same structure as showed in the previous example. We create context mapping among this context node and the context views V_PHASE1, V_PHASE2 and V_PHASE3.
Fig. 9.83 Context structure
182
9 User Interface Elements (UI elements), Static and Dynamic Programming
The layout of the view V_VIEW is presented in Fig. 9.84.
Fig. 9.84 The V_VIEW layout
This view has two outbound plugs defined: OP_TO_V_PHASE2 and OP_TO_V_PHASE3. The view V_PHASE1 has no inbound plug, the view V_PHASE2 has an inbound plug named IP_V_PHASE2 and the view PHASE_3 has an inbound plug named IP_V_PHASE3. The window structure is presented in Fig. 9.85.
Fig. 9.85 Window structure
9.4 Complex
183
The view V_PHASE1 is shown in the ViewControllerUIElement first time when the screen is rendered, this view being defined as default view. We have to dynamically set the attributes values for SELECTEDPHASE, STATS2, STATUS3 and ENABLED_NEXT. To do this, we use the wdDoInit Hook method (Listing 9.32).
METHOD wddoinit. DATA lr_node TYPE REF TO if_wd_context_node. DATA ls_data TYPE if_v_view=>element_dynamic. lr_node = wd_context->get_child_node( 'DYNAMIC' ). ls_data-enabled_next = abap_true. ls_data-status2 = CL_WD_PHASE=>E_STATUS-WARNING. ls_data-status3 = CL_WD_PHASE=>E_STATUS-WARNING. ls_data-selectedphase = 'PHASE1'. lr_node->set_static_attributes( ls_data ). ENDMETHOD.
Listing 9.32 The wdDoInit Hook method
As we can see, we selected the first phase: ls_data-selectedphase = ‘PHASE1’ and we set the Phase2 and Phase3 with the Warning status ls_data-status2 = cl_wd_phase ) e_status-warning. ls_data-status3 = cl_wd_phase ) e_status-warning. and the Next button enabled (Fig. 9.86).
Fig. 9.86 Runtime
When the user presses the button, the Framework triggers the event handler method onactionnext (Listing 9.33).
184
9 User Interface Elements (UI elements), Static and Dynamic Programming METHOD onactionnext. DATA lr_node TYPE REF TO if_wd_context_node. DATA ls_data TYPE if_v_view=>element_dynamic. DATA lv_phase TYPE string. lr_node = wd_context->get_child_node( 'DYNAMIC' ). lr_node->get_attribute( EXPORTING name = 'SELECTEDPHASE' IMPORTING value = lv_phase ). CASE lv_phase. WHEN 'PHASE1'. ls_data-selectedphase = 'PHASE2'. ls_data-enabled_next = abap_true. ls_data-status2 = cl_wd_phase=>e_status-completed. ls_data-status3 = cl_wd_phase=>e_status-warning. wd_this->fire_op_to_v_phase2_plg( ). WHEN 'PHASE2'. ls_data-selectedphase = 'PHASE3'. ls_data-enabled_next = abap_false. ls_data-status2 = cl_wd_phase=>e_status-completed. ls_data-status3 = cl_wd_phase=>e_status-completed. wd_this->fire_op_to_v_phase3_plg( ). WHEN OTHERS. ls_data-enabled_next = abap_false. ENDCASE. lr_node->set_static_attributes( ls_data ). ENDMETHOD.
Listing 9.33 The onactionnext event handler method
As we can see, we make active the Phase2 ls_data-selectedphase ¼ ‘PHASE2’ we set the Phase2 with completed status and Phase3 with warning status ls_data-status2 ¼ cl_wd_phase ) e_status-completed.ls_data-status3 = cl_wd_phase ) e_status-warning. and the Next button enabled (Fig. 9.87).
Fig. 9.87 Runtime
For the next press of the NEXT button, we set the Phase2 and Phase3 with completed status
9.4 Complex
185
ls_data-status2 ¼ cl_wd_phase)e_status-completed. ls_data-status3 ¼ cl_wd_phase)e_status-completed.we make active the last Phase, ls_data-selectedphase = ‘PHASE3’. and we deactivate the NEXT button (Fig. 9.88).
Fig. 9.88 Runtime
9.4.3.1
Dynamic Programming
RUNTIME CLASS: CL_WD_PHASE_INDICATOR Hereunder, we present a table showing the correspondence between the view designer name and the runtime name, with the proper types, in case of dynamic programming of a PhaseIndicator UI element (Table 9.22).
Table 9.22 Dynamic programming View designer name Runtime name Type selectedPhase SELECTED_PHASE String firstVisiblephase FIRST_VISIBLE_PHASE String backgroundDesign BACKGROUND_DESIGN WDUI_PHASE_IND_BGD_DESIGN CL_WD_PHASE_INDICATOR)E_BACKGROUND_DESIGN-EMPHASIZED CL_WD_PHASE_INDICATOR)E_BACKGROUND_DESIGN-TRANSPARENT
For the PhaseIndicator UI element, we have, as aggregation, the Phase element. It has the CL_WD_PHASE runtime class. The implementation of a dynamic PhaseIndicator UI element with two Phases contains the following statements (Listing 9.34):
186
9 User Interface Elements (UI elements), Static and Dynamic Programming METHOD wddomodifyview. DATA lr_container TYPE REF TO cl_wd_uielement_container. DATA lr_flow_data TYPE REF TO cl_wd_flow_data. DATA lr_phaseindicator TYPE REF TO cl_wd_phase_indicator. DATA lr_phase1 TYPE REF TO cl_wd_phase. DATA lr_phase2 TYPE REF TO cl_wd_phase. IF first_time EQ abap_true. lr_container ?= view->get_element( 'ROOTUIELEMENTCONTAINER' ). lr_phaseindicator = cl_wd_phase_indicator=>new_phase_indicator( id = 'PI_PHASEINDICATOR' bind_selected_phase = 'DYNAMIC.SELECTEDPHASE' first_visible_phase = 'PHASE1' background_design = cl_wd_phase_indicator=>e_background_designtransparent ). lr_flow_data = cl_wd_flow_data=>new_flow_data( element = lr_phaseindicator ). lr_container->add_child( lr_phaseindicator ). lr_phase1 = cl_wd_phase=>new_phase( id = 'PHASE1' description = 'PHASE 1' status = cl_wd_phase=>e_status-completed ). lr_phaseindicator->add_phase( the_phase = lr_phase1 ). lr_phase2 = cl_wd_phase=>new_phase( id = 'PHASE2' description = 'PHASE 2' bind_status = 'DYNAMIC.STATUS2' ). lr_phaseindicator->add_phase( the_phase = lr_phase2 ). ENDIF. ENDMETHOD.
Listing 9.34 Dynamic programming of a PhaseIndicator UI element
9.4.4
Tree – Sequential Implementation
With this UI element, we can visualise the hierarchy defined in the context. For this UI element, we can use: l
l
A sequential implementation with a non-recursive node in case the number of levels can be specified at design time A recursive implementation with a recursive node in case the number of levels is not known at design time. We create a WD component (Fig. 9.89).
Fig. 9.89 WD component structure
9.4 Complex
187
In this case (sequential implementation), we don’t need a recursive node. A context node TREE is created in the context node of the view controller. It has the cardinality 1. . .1 and is Singleton. Under this context node, we create another context node TREE_NODE with two attributes. Under this context node, we create another context node TREE_LEAF with an attribute (Fig. 9.90).
Fig. 9.90 Context structure
The attributes STUDENTNAME, VALUE and STUDENTINFO are of STRING type. The context node TREE_LEAF is not Singleton, because we need to create an instance of this node for each element of the TREE_NODE context node. In the STUDENTNAME attribute, we hold the name of each student; for each student we have proper information held in the attribute STUDENTINFO. In a Tree UI element, we can insert Node Types of type TreeItemType and TreeNodeType, to specify which subnodes and which context attributes are going to be displayed (Fig. 9.91).
Fig. 9.91 Inserting Node Type
The view layout is presented in Fig. 9.92.
188
9 User Interface Elements (UI elements), Static and Dynamic Programming
Fig. 9.92 View layout
The TreeItemType element – TREE_IT in our case – describes a node that cannot have children and is always displayed as leaf elements. The TreeNodeType element – TREE_NT in our case – describes a node that can have children and is displayed as tree nodes. In Fig. 9.93 we show the binding of the context to the tree elements.
Fig. 9.93 Binding of the Context to the Tree elements
The context node TREE_NODE is populated via the supply function method (Listing 9.35).
Listing 9.35 Populating the attributes of the TREE_NODE context node
METHOD supply_tree_node. DATA: ls_student TYPE if_v_view=>element_tree_node, lt_student LIKE TABLE OF ls_student. ls_student-studentname = 'Ionescu Ana Maria'. ls_student-value = 'A'. APPEND ls_student TO lt_student. ls_student-studentname = 'Marinescu Loredana'. ls_student-value = 'B'. APPEND ls_student TO lt_student. ls_student-studentname = 'Marton Luminita'. ls_student-value = 'C'. APPEND ls_student TO lt_student. node->bind_table( lt_student ). ENDMETHOD.
9.4 Complex
189
The values for the child node TREE_LEAF are set in the same way via a supply function method (Listing 9.36). METHOD supply_tree_leaf. DATA: ls_student TYPE if_v_view=>element_tree_leaf, lt_student LIKE TABLE OF ls_student. DATA: lv_value TYPE string. parent_element->get_attribute( EXPORTING name = 'VALUE' IMPORTING value = lv_value ). CASE lv_value. WHEN 'A'. ls_student-studentinfo = 'Article - YES'. APPEND ls_student TO lt_student. ls_student-studentinfo = 'Exam - 5'. APPEND ls_student TO lt_student. ls_student-studentinfo = 'Academic year - II'. APPEND ls_student TO lt_student. WHEN 'B'. ls_student-studentinfo = 'Article - NO'. APPEND ls_student TO lt_student. ls_student-studentinfo = 'Academic year - I'. APPEND ls_student TO lt_student. WHEN OTHERS. ls_student-studentinfo = 'Article - YES'. APPEND ls_student TO lt_student. ls_student-studentinfo = 'Exam - 3'. APPEND ls_student TO lt_student. ls_student-studentinfo = 'Academic year - IV'. APPEND ls_student TO lt_student. ENDCASE. node->bind_table( lt_student ). ENDMETHOD.
Listing 9.36 Populating the attributes of the TREE_LEAF context node
At runtime, this method is called for each element of the parent context node (Fig. 9.94). Element 1 Student A
Element 2 Student B
Element 3 Student C
Ionescu Anamaria
Marinescu Loredana
Marton Luminita
Element 11 Article-yes
Element 31
Article - no
Article - yes
Element 12
Element 22
Element 32
Exam - 5
Academic year - I
Exam - 3
Element 13 Academic year - II
Fig. 9.94 Runtime
Element 21
Element 33 Academic year - IV
190
9.4.4.1
9 User Interface Elements (UI elements), Static and Dynamic Programming
Dynamic Programming
RUNTIME CLASS: CL_WD_TREE Hereunder, we present a table showing the correspondence between the view designer name and the runtime name, with the proper types, in case of dynamic programming of a Tree UI element (Table 9.23). Table 9.23 Dynamic programming View designer name Runtime name dataSource DATA_SOURCE Title TITLE defaultNodeIconSource
DEFAULT_NODE_ICON_ SOURCE
Type Object WDY_MD_TRANSLATABLE_ TEXT STRING
For the Tree UI element, we have, as aggregation, the Node Types: TreeItemType and TreeNodeType. The TreeItemType element has the CL_WD_TREE_ ITEM_TYPE runtime class and the TreeNodeType element has the CL_WD_ TREE_NODE_TYPE runtime class. The implementation of a dynamic Tree UI element with two node types (TreeNodeType and TreeItemType) contains the following statements (Listing 9.37): METHOD wddomodifyview. DATA lr_container TYPE REF TO cl_wd_uielement_container. DATA lr_flow_data TYPE REF TO cl_wd_flow_data. DATA lr_tree TYPE REF TO cl_wd_tree. DATA lr_treenode TYPE REF TO cl_wd_tree_node_type. DATA lr_treeitem TYPE REF TO cl_wd_tree_item_type. IF first_time EQ abap_true. lr_container ?= view->get_element('ROOTUIELEMENTCONTAINER'). lr_tree = cl_wd_tree=>new_tree( id = 'TRE_SEQUENTIAL' bind_data_source = 'TREE' title = 'Student info' default_node_icon_source = '~Icon/CheckedOk' ). lr_flow_data = cl_wd_flow_data=>new_flow_data( element = lr_tree ). lr_container->add_child( lr_tree ). lr_treenode = cl_wd_tree_node_type=>new_tree_node_type( id = 'TREE_NT' bind_data_source = 'TREE.TREE_NODE' bind_text = 'TREE.TREE_NODE.STUDENTNAME' ). lr_treeitem = cl_wd_tree_item_type=>new_tree_item_type( id = 'TREE_IT' bind_data_source = 'TREE.TREE_NODE.TREE_LEAF' bind_text = 'TREE.TREE_NODE.TREE_LEAF.STUDENTINFO' ). lr_tree->add_node_type( index = 1 the_node_type = lr_treenode ). lr_tree->add_node_type( index = 2 the_node_type = lr_treeitem ). ENDIF. ENDMETHOD.
Listing 9.37 Dynamic programming
9.4 Complex
9.4.5
191
DateNavigator
This UI element offers the possibilities to display and navigate in a calendar and to enter dates, by choosing a year, a month, a day or a range of dates, from the showed calendar. Hereunder, we present a table with some of the DataNavigator properties that can be bound, and the attribute type in case the property is bindable (Table 9.24). Table 9.24 Some of the DataNavigator UI element properties Name Type firstDayOfWeek WDUI_DAY_OF_WEEK firstSelectedDate D lastSelectedDate D selectionMode WDUI_DATE_SELECTION_MODE startsWith D
Initial value Auto
Single
Bindable Yes Yes Yes Yes Yes
We create a WD Component named Y_UI_DATENAVIGATOR. In the context view, we create three attributes: MONTH, WEEK and DAY of STRING type, and two context nodes: l
l
LEGEND, Cardinality 0. . .n, supply function named SUPPLY_LEGEND, attributes: CATEGORY of WDY_MD_DATE_MARKING_CATEGORY type and TEXT of STRING type MARKING, Cardinality 0. . .n, supply function named SUPPLY_MARKING, attributes: CATEGORY of WDY_MD_DATE_MARKING_CATEGORY type and DATE of D type.
In the view layout, we insert a DateNavigator UI element with a DateNavigatorLegend and DateNavigatorMarking, Fig. 9.95. By using the DateNavigatorLegend element, we can add a legend for the DateNavigator, and with the DateNavigatorMarking element, we can highlight entries of a specific category within the DateNavigator UI element.
Fig. 9.95 Context view and DateNavigatorLegend, DateNavigatorMarking properties
192
9 User Interface Elements (UI elements), Static and Dynamic Programming
The most important properties of the DateNavigatorLegend element are: l
l l
“Category”, which allows us to create the legend categories (in format one, two, three and four). It shall be bound to a context attribute that stores these categories. “Text”, which stores the texts, describing each category. “DataSource”, which shall be bound to a context node, which stores the categories and the texts of the legend entries. The most important properties of the DateNavigatorMarking element are:
l
l
l
l
“Category”, which shall be bound to a context attribute that stores the category of the highlighted data. “DataSource”, which shall be bound to a context node which stores the categories, data and tooltip of the highlighted data. “Tooltip” is not necessarily bindable. In our case, we have not created an attribute for the tooltip, because we don’t want to display a quick info text when the user passes the mouse pointer over the highlighted data of the DateNavigator UI element. “Data” shall be bound to a context attribute that stores the date of the highlighted data. The view layout is presented in Fig. 9.96.
Fig. 9.96 View layout
9.4 Complex
193
The DateNavigator UI element has many properties and events. In our case, we have changed the properties: . In this way, we have chosen Sunday as the first day of the week in our calendar. . In this way, we show 3 months in our calendar. . We have chosen from the list the range option, because we want to offer the possibility to select the range of dates. . We have set the starting date of our calendar. To be able to show, in the TextView UI elements, the week, the day or the month that the end-user selects in our calendar, we have used the events: onDaySelect, onMonthSelect and onWeekSelect (Fig. 9.97). Fig. 9.97 Events of the DataNavigator UI element
First of all, we have to populate our nodes with values. The Listing 9.38 shows the SUPPLY_LEGEND supply function method. METHOD supply_legend. DATA: ls_legend TYPE wd_this->element_legend, lt_legend LIKE TABLE OF ls_legend. ls_legend-category = cl_wd_date_nav_legend=>e_category-one. ls_legend-text = 'Doors open day'. APPEND ls_legend TO lt_legend. ls_legend-category = cl_wd_date_nav_legend=>e_category-two. ls_legend-text = 'Operating teams trip'. APPEND ls_legend TO lt_legend. ls_legend-category = cl_wd_date_nav_legend=>e_category-three. ls_legend-text = 'Happy hour'. INSERT ls_legend INTO TABLE lt_legend. node->bind_table( lt_legend ). ENDMETHOD.
Listing 9.38 The SUPPLY_LEGEND supply function method
We create three legend categories (one, two and three), with the texts: “Doors open day” for the first category, “Operating teams trip” for the second category and “Happy hour” for the third category.
194
9 User Interface Elements (UI elements), Static and Dynamic Programming
The Listing 9.39 shows the SUPPLY_MARKING supply function method required to populate with values the MARKING node.
METHOD supply_legend. DATA: ls_legend TYPE wd_this->element_legend, lt_legend LIKE TABLE OF ls_legend. ls_legend-category = cl_wd_date_nav_legend=>e_category-one. ls_legend-text = 'Doors open day'. APPEND ls_legend TO lt_legend. ls_legend-category = cl_wd_date_nav_legend=>e_category-two. ls_legend-text = 'Operating teams trip'. APPEND ls_legend TO lt_legend. ls_legend-category = cl_wd_date_nav_legend=>e_category-three. ls_legend-text = 'Happy hour'. INSERT ls_legend INTO TABLE lt_legend. node->bind_table( lt_legend ). ENDMETHOD.
Listing 9.39 The SUPPLY_MARKING supply function method
In this way we mark (highlight), for the first category, the day 11.08.2009, for the second category, the day 21.08.2009, and for the third category, the day 24.08.2009. When the user selects a day in our calendar, the Framework triggers the event handler method onactionon_day_select (Fig. 9.98).
Fig. 9.98 The onactionon_day_select event handler method
As import parameter, for our event handler method, we have the parameter named DAY of D type that holds the selected day. We pass this value in our DAY attribute created in the context view. When the user selects a Week in our calendar, the Framework triggers the event handler method onactionon_week_select (Fig. 9.99).
9.4 Complex
195
Fig. 9.99 The onactionon_week_select event handler method
As import parameter, for our event handler method, we have the parameters: WEEK of I type that holds the selected week and YEAR of I type that holds the corresponding year of the selected week. We pass these values in our WEEK attribute created in the context view. When the user selects a Month in our calendar, the Framework triggers the event handler method onactionon_month_select (Fig. 9.100).
Fig. 9.100 The onactionon_month_select event handler method
As import parameters, for our event handler method, we have: MONTH of I type that holds the selected month and YEAR of I type that holds the corresponding year
196
9 User Interface Elements (UI elements), Static and Dynamic Programming
of the selected month. We pass these values in our MONTH attribute created in context view. At runtime, we have: (Fig. 9.101):
Fig. 9.101 Runtime
9.4.5.1
Dynamic Programming
RUNTIME CLASS: CL_WD_DATE_NAVIGATOR Hereunder, we present a table showing the correspondence between the view designer name and the runtime name, with the proper types, in case of dynamic programming of a DateNavigation UI element (Table 9.25).
Table 9.25 Dynamic programming View designer name Runtime name Type firstDayOfWeek FIRST_DAY_OF_WEEK WDUI_DAY_OF_WEEK CL_WD_DATE_NAVIGATOR)E_FIRST_DAY_OF_WEEK-SUNDAY CL_WD_DATE_NAVIGATOR)E_FIRST_DAY_OF_WEEK-AUTO monthsPerColumn MONTHS_PER_COLUMN I monthsPerRow MONTHS_PER_ROW I startsWith STARTS_WITH D selectionMode SELECTION_MODE WDUI_DATE_SELECTION_MODE CL_WD_DATE_NAVIGATOR)E_SELECTION_MODE-NONE CL_WD_DATE_NAVIGATOR)E_SELECTION_MODE-RANGE CL_WD_DATE_NAVIGATOR)E_SELECTION_MODE-SINGLE
9.5 Graphic
197
The implementation of a dynamic DateNavigator UI element with elements: DateNavigatorLegent and DateNavigatorMarking, contains the following statements (Listing 9.40):
METHOD wddomodifyview. DATA lr_date_navigator TYPE REF TO cl_wd_date_navigator. DATA lr_flow_data TYPE REF TO cl_wd_flow_data. DATA lr_container TYPE REF TO cl_wd_uielement_container. DATA lr_datenav_legend TYPE REF TO cl_wd_date_nav_legend. DATA lr_datenav_marking TYPE REF TO cl_wd_date_nav_marking. IF first_time EQ abap_true. lr_container ?= view->get_element( 'ROOTUIELEMENTCONTAINER' ). lr_date_navigator = cl_wd_date_navigator=>new_date_navigator( id = 'DATENAVIGATOR' first_day_of_week = cl_wd_date_navigator=>e_first_day_of_week-sunday months_per_column = 1 months_per_row = 3 selection_mode = cl_wd_date_navigator=>e_selection_mode-range starts_with = '20090801' on_day_select = 'ON_DAY_SELECT' on_month_select = 'ON_MONTH_SELECT' on_week_select = 'ON_WEEK_SELECT' ). lr_flow_data = cl_wd_flow_data=>new_flow_data( element = lr_date_navigator ). lr_container->add_child( lr_date_navigator ). lr_datenav_legend = cl_wd_date_nav_legend=>new_date_nav_legend( id = 'DATENAVIGATORLEGEND' bind_category = 'LEGEND.CATEGORY' bind_data_source = 'LEGEND' bind_text = 'LEGEND.TEXT' ). lr_date_navigator->set_legend( the_legend = lr_datenav_legend ). lr_datenav_marking = cl_wd_date_nav_marking=>new_date_nav_marking( id = 'DATENAVIGATORMARKING' bind_category = 'MARKING.CATEGORY' bind_data_source = 'MARKING' bind_date = 'MARKING.DATE' ). lr_date_navigator->set_marking( the_marking = lr_datenav_marking ). ENDIF. ENDMETHOD.
Listing 9.40 Dynamic programming of a DataNavigator UI element
9.5
Graphic
This category contains UI elements that help us to work with graphics, maps, etc. Hereunder, we present some of the UI Elements included in this category.
198
9.5.1
9 User Interface Elements (UI elements), Static and Dynamic Programming
Image
This UI element enables us to integrate graphics in our WD application. Same as other UI elements, it has some properties. Hereunder, we show a table with some of the Image UI element properties that can be bound, and the attribute type in case the property is bindable (Table 9.26).
Table 9.26 Some of the Image UI element properties Name Type Border I adjustImageSize WDY_BOOLEAN Height STRING Width STRING isDecorative WDY_BOOLEAN Source STRING
Initial value 0 False
False
Bindable Yes Yes Yes Yes Yes Yes
We create a WD Component, where we can choose among three images and we can manipulate the current image via the data held in the context. The WD component structure is presented in Fig. 9.102.
Fig. 9.102 WD component structure
We import three images in JPG format. As we have mentioned, to import an image into a MIME folder, we have to choose Create ! Mime Object ! Import from the contextual menu, shown by right-clicking on the WD component name. The context node DYNAMIC is Singleton, cardinality 1. . .1. The attributes WIDTH and HEIGH are STRING type and the attribute BORDER is I type. We use these attributes to manipulate the properties of the Image UI element. For the attributes WIDTH, BORDER and HEIGH, it is defined the data binding to the properties (with the same names) of the UI element Image, Fig. 9.103.
9.5 Graphic
199
Fig. 9.103 Context structure and data binding
The context node DROPDOWNBYINDEX has the dictionary structure SHSVALSTR2, cardinality 0. . .n, Singleton. We have defined a data binding between the attribute KEY and the property texts of the dropDownByIndex UI element. The attribute VALUE is used to manipulate the property source of the Image UI element. This property defines the name of the image file shown on the screen. The layout is presented in Fig. 9.104.
Fig. 9.104 View Layout structure
To populate with values the context attributes of the context node DROPDOWNBYINDEX, we use the supply function method shown in the Listing 9.41.
200
9 User Interface Elements (UI elements), Static and Dynamic Programming
Listing 9.41 Supply function method
METHOD supply_dropdownbyindex. DATA: ls_image TYPE wd_this->element_dropdownbyindex, lt_image LIKE TABLE OF ls_image. ls_image-key = 'Germany'. ls_image-value = 'deutschland.jpg'. APPEND ls_image TO lt_image. ls_image-key = 'France'. ls_image-value = 'france.jpg'. APPEND ls_image TO lt_image. ls_image-key = 'Italy'. ls_image-value = 'italia.jpg'. APPEND ls_image TO lt_image. node->bind_table( new_items = lt_image set_initial_elements = abap_true ). ENDMETHOD.
At runtime, we have (Fig. 9.105):
Fig. 9.105 Runtime
9.5.1.1
Dynamic Programming
RUNTIME CLASS: CL_WD_IMAGE Hereunder, we present a table showing the correspondence between the view designer name and the runtime name, with the proper types, in case of dynamic programming of an Image UI element (Table 9.27).
9.5 Graphic
201 Table 9.27 Dynamic programming View designer name Runtime name Border BORDER Source SOURCE Width WIDTH Height HEIGHT
Type I STRING STRING STRING
The implementation of a dynamic Image UI element contains the following statements (Listing 9.42):
data lr_image type ref to cl_wd_image. Ir_image = cl_wd_image=>new_image( id = ‘IMG_IMAGE’ bind_width = ‘DYNAMIC.WIDTH’ bind_height = ‘DYNAMIC.HEIGHT’ bind_border = ‘DYNAMIC.BORDER’ bind_source = ‘DROPDOWNBYINDEX.VALUE’ ).
Listing 9.42 Dynamic creation of an Image UI element
9.5.2
BusinessGraphics
This UI element enables us to use several chart types in our WD application. The Internet Graphics Service (IGS) helps us to work with this UI element, being able to show graphics in a browser. The chart engine is a C++ library that supports chart types, from simple charts (e.g. bars or pie) to complex charts (e.g. gantt). We create a WD Component with the structure presented in Fig. 9.106. By using the BusinessGraphics UI element, we show the graphical illustration of the data stored in our database table YPERSON.
Fig. 9.106 WD component structure
202
9 User Interface Elements (UI elements), Static and Dynamic Programming
The context view has the structure presented in Fig. 9.107.
Fig. 9.107 Context structure
The node person has the dictionary structure YPERSON, cardinality 1...n, Singleton. From this structure, we choose only LASTNAME and AGE. We have used a chart of columns type, to graphically display the data contained by the columns of our database table. The View Layout is presented in Fig. 9.108.
Fig. 9.108 View Layout
By using the supply function, we populate the node PERSON with data from the database table YPERSON. We select all the data from the two columns LASTNAME and AGE.
9.5 Graphic
203
At runtime, we have (Fig. 9.109): 25 20 15 10 5 0 ANTONETA MARIA
ANA MARIA CORINA
ANTON GEORGE MARIA
Candidate’s age
Fig. 9.109 Runtime
To perform customizing settings for business graphics, we have to use the SAP Chart Designer. We access this tool by double-clicking on the chart picture, in the view layout. Now, the SAP Chart Designer is open and we can customise our chart (Fig. 9.110).
Fig. 9.110 Chart designer
204
9 User Interface Elements (UI elements), Static and Dynamic Programming
We save the settings we made; the Framework generates a MIME file in XML format and sets the property customizing of the BusinessGraphics UI element (Fig. 9.111).
Fig. 9.111 Saving the customizing in a XML file
Figure 9.112 shows the runtime result. Candidate Age Graphic 18–45 25 Candidate’s age 20 15 10 5 0 ANTONET A MARIA
ANA MARI A CORINA
ANTON GEORGE MARIA
Fig. 9.112 Runtime result
9.5.2.1
Dynamic Programming
RUNTIME CLASS: CL_WD_BUSINESS_GRAPHICS Hereunder, we present a table showing the correspondence between the view designer name and the runtime name, with the proper types, in case of dynamic programming of a BusinessGraphics UI element (Table 9.28). For a BusinessGraphics UI element, we have, as aggregation, Category and Series. The Category object has the CL_WD_CATEGORY runtime class. The Series can be Series, runtime CL_WD_SERIES or SimpleSeries, runtime class CL_WD_SIMPLE_SERIES.
9.5 Graphic
205
Table 9.28 Dynamic programming View designer name Runtime name Type Customizing CUSTOMIZING String Dimension DIMENSION WDUI_BGDIMENSION dimension: pseudo_three CL_WD_BUSINESS_GRAPHICS)E_DIMENSIONPSEUDO_THREE dimension: three CL_WD_BUSINESS_GRAPHICS)E_DIMENSION-THREE dimension: two CL_WD_BUSINESS_GRAPHICS)E_DIMENSION-TWO chartType CHART_TYPE WDUI_BGTYPE chartType: columns CL_WD_BUSINESS_GRAPHICS)E_CHART_TYPE-COLUMNS chartType: area CL_WD_BUSINESS_GRAPHICS)E_CHART_TYPE-AREA chartType: bars CL_WD_BUSINESS_GRAPHICS)E_CHART_TYPE-BARS
The implementation of a dynamic BusinessGraphics UI element (with a SimpleSeries and a Category) contains the following statements (Listing 9.43). METHOD wddomodifyview. DATA lr_flow_data TYPE REF TO cl_wd_flow_data. DATA lr_container TYPE REF TO cl_wd_uielement_container. DATA lr_businessgraphics TYPE REF TO cl_wd_business_graphics. DATA lr_category TYPE REF TO cl_wd_category. DATA lr_simpleseries TYPE REF TO cl_wd_simple_series. IF first_time EQ abap_true. lr_container ?= view->get_element( 'ROOTUIELEMENTCONTAINER' ). lr_businessgraphics = cl_wd_business_graphics=>new_business_graphics( id = 'BGR' chart_type = cl_wd_business_graphics=>e_chart_type-columns dimension = cl_wd_business_graphics=>e_dimension-two height = 300 width = 300 bind_series_source = 'PERSON' customizing = 'D57PJD6VB3MQAZR78XQHWTMIT.xml' ). lr_flow_data = cl_wd_flow_data=>new_flow_data( element = lr_businessgraphics ). lr_container->add_child( lr_businessgraphics ). lr_category ?= cl_wd_category=>new_category( id = 'CATEGORY' bind_description = 'PERSON.LASTNAME' tooltip = 'Candidates last name' ). lr_simpleseries ?= cl_wd_simple_series=>new_simple_series( id = 'SIMPLESERIES' label = 'Candidate Age' bind_value = 'PERSON.AGE' tooltip = 'Candidate Age' ). lr_businessgraphics->set_category( the_category = lr_category ). lr_businessgraphics->add_series( the_series = lr_simpleseries ). ENDIF. ENDMETHOD.
Listing 9.43 Dynamic creation of a BusinessGraphics UI element
206
9.6
9 User Interface Elements (UI elements), Static and Dynamic Programming
Integration
This category contains UI elements that help us to integrate, in our Web Dynpro applications, different other technologies. Hereunder, we present some of the UI elements included in this category.
9.6.1
The InteractiveForm
Adobe Document Service (ADS) is the software developed by Adobe, written in Java and C++, embedded in SAP development environment to create forms. The communications between the ABAP stack and Java stack is realised via a Web Service. By using the SM59 transaction, we can see the ADS – HTTP connection to an external server – j2ee engine (Fig. 9.113).
Fig. 9.113 ADS – HTTP connection to an external server
To ensure that ADS is correctly configured, we can execute the program FP_PDF_TEST_00 by using the transactions SE38 or SA38. In case the configuration is correct, we receive, as output, the version number of the ADS we have installed (Fig. 9.114)
9.6 Integration
207
Fig. 9.114 Checking if the ADS is correctly configured
To be able to create forms, we have to locally install the Adobe LifeCycle Designer. Tip For more information, refer to the SAP PRESS book, SAP Interactive Forms by Adobe (Hauser et al.)
Firstly, we create an example where we use a non-interactive PDF form in a WD component. The WD component structure has the structure presented in Fig. 9.115. Fig. 9.115 WD component structure
In the view layout, we add an InteractiveForm UI element. After this, we have to bind its properties pdfSource and dataSource to the context. The pdfSource shall be bound to an attribute of XSTRING type, in order to be used to store the generated PDF document. The dataSource property has to be bound to the context node that provides the data for our PDF form. This node can have the cardinality 0. . .1 or 1. . .1. Under this node, we create other context nodes. In our case, we have only a node named PERSON, cardinality 1. . .n that has, as dictionary structure, our database table YPERSON defined in the ABAP Dictionary (populate via supply function). The context structure and the view layout are presented in Fig. 9.116.
208
9 User Interface Elements (UI elements), Static and Dynamic Programming
Fig. 9.116 Data binding
Through the property templateSource, we specify the unique name of the Adobe Form we use. We enter the name of the Form and then, by double-clicking, we realise a forward navigation, because this Form does not exist yet. This action will open a pop-up window, where we have to enter the interface name (Fig. 9.117). The generated form will use a XML Schema – Based Interface.
Double click
Fig. 9.117 Specifying the form interface
9.6 Integration
209
By using the CONTEXT button, we can use our context node DATASOURCE to create the interface. The structure of this context node is displayed in the tab Data View of Adobe LifeCycle Designer (Fig. 9.118).
Fig. 9.118 The form builder
The context elements can be simply dragged and dropped onto the form layout, or we can use the Table Assistant to design the look of our table (Fig. 9.119).
Drag and drop
Fig. 9.119 Creating form layout
Because our node has the cardinality 1. . . n, the table Header is automatically created. We can manually design the layout of the table by using the tools located in the right side of the Form Builder.
210
9 User Interface Elements (UI elements), Static and Dynamic Programming
We can obtain more information about using LiveCycle Designer in the SAP environment by using the Adobe LiveCycle Designer help (through F1) or the menu Help ! Adobe LifeCycle Designer Help. We set a Standard layout type; we activate the Form, the Interface and our WD Component. Then, we can run the application (Fig. 9.120).
Fig. 9.120 Runtime
For the interactive forms, we must set TRUE the “enabled” property of the InteractiveForm UI element, and FALSE the “read only” property of the same InteractiveForm UI element. Then, we have to attach an action to its onSubmit event, because the Framework triggers the attached event handler method when the user presses a special Submit button included in the Adobe Designer. We create a very simple example required to show how we can use an interactive PDF form into a view, and how we can import a PDF template into the Adobe Designer. We create a WD Component that has the view context presented in Fig. 9.121. Cardinality 1…1; it provides the data for our interactive PDF form Cardinality 1…1 YPERSON dictionary structure Attribute of DATUM type, required to show the current data into the Form Attribute of XSTRING type, required to store the generated interactive PDF document
Fig. 9.121 View Context structure
The properties of the InteractiveForm UI element are presented in Fig. 9.122. As we can see, we have an onSubmit event named “Save”, the enabled property is set TRUE and the readOnly property is set FALSE. Because we don’t want to use an activeX control, we left the displayType property as native (default).
9.6 Integration
211
Fig. 9.122 InteractiveForm UI element properties
When the user presses the Submit button, the Framework triggers the event handler method onactionsave from our View Methods tab (Listing 9.44). METHOD onactionsave. DATA: lr_node TYPE REF TO if_wd_context_node, lr_subnode TYPE REF TO if_wd_context_node, ls_subnode TYPE wd_this->element_candidate. DATA: lv_firstname LIKE ls_subnode-firstname, lv_lastname LIKE ls_subnode-lastname, lv_telephone LIKE ls_subnode-telephone. lr_node = wd_context->get_child_node( 'DATASOURCE' ). lr_subnode = lr_node->get_child_node( 'CANDIDATE' ). lr_subnode->get_static_attributes( IMPORTING static_attributes = ls_subnode ). lv_firstname = ls_subnode-firstname. lv_lastname = ls_subnode-lastname. lv_telephone = ls_subnode-telephone. IF lv_telephone IS INITIAL OR lv_firstname IS INITIAL OR lv_lastname IS INITIAL. wd_this->atr_mm>report_message( message_text ='All the fields are mandatory!' message_type = 2 ). ELSE. wd_this->atr_mm->report_message( message_text ='Data successfully saved!' message_type = 0 ). ENDIF. ENDMETHOD.
Listing 9.44 The onactionsave event handler method
212
9 User Interface Elements (UI elements), Static and Dynamic Programming
When the end user presses the Submit button, we check if he has entered the required values: first name, last name and his telephone number. In case the required values are correctly entered, we show an information message; otherwise, we inform him that all the fields are mandatory. In this case, we have created our own attribute in the Attribute tab (Fig. 9.123).
Fig. 9.123 User defined attribute
To have access to the attribute created by us, we have to use the wd_this self reference. By using the wdDoInit Hook method, we pass the reference to the Message Manager in the ATR_MM attribute: DATA lr_current_controller TYPE REF TO if_wd_controller. lr_current_controller ?¼ wd_this!wd_get_api( ). wd_this!atr_mm ¼ lr_current_controller!get_message_manager( ). By using the same wdDoInit Hook method, we have set the value of the DATA attribute: sy-datum. In this way, we show the current data into the Form. After this, we use the forward navigation to create our form objects: the YINTERACTIVE form and the YINTERACTIVE interface. Then, we import a PDF template file into our new generated form. The template file has been created in PowerPoint (one slide) and converted into Adobe PDF (Fig. 9.124). Through the menu Tools ! Import, we can perform the importing operation (Fig. 9.125). As a result, the PDF template is inserted into our Form (Fig. 9.126). We simply drag and drop the context elements onto the form layout. After this, we insert a Reset button from the Standard library, and we use the Web Dynpro Native library to insert a Submit button required to submit the data. For the native version (interactive scenario), we have used a Zero Client Installation (ZCI) Layout type and we have inserted a ZCI script by using the menu: Utilities ! Insert Web Dynpro Script (or through the FP_ZCI_UPDATE report). In case we want to use an ActiveX control, we have to set the displayType property as ActiveX, to use the Web Dynpro ActiveX library and a proper
9.6 Integration
213
Fig. 9.124 Structure of PDFTEMPLATE file
Fig. 9.125 Importing an Adobe PDF File
Layout type. In this way, the form is displayed via Active Components Framework (ACF). We activate the Form, the Interface and our WD Component. Then, we can run the application.
214
9 User Interface Elements (UI elements), Static and Dynamic Programming
Fig. 9.126 Layout Form
9.6.1.1
Dynamic Programming
RUNTIME CLASS: CL_WD_INTERACTIVE_FORM Hereunder, we present a table showing the correspondence between the view designer name and the runtime name, with the proper types, in case of dynamic programming of an InteractiveForm UI element (Table 9.29). Table 9.29 Dynamic programming View designer name Runtime name Type pdfSource PDF_SOURCE XSTRING Enabled ENABLED WDY_BOOLEAN dataSource DATA_SOURCE OBJECT Width WIDTH STRING Height HEIGHT STRING displayType DISPLAY_TYPE activeX: CL_WD_INTERACTIVE_FORM)E_DISPLAY_TYPE-ACTIVE_X Native: CL_WD_INTERACTIVE_FORM)E_DISPLAY_TYPE-NATIVE
The implementation of a dynamic InteractiveForm UI element (non – interactive) contains the following statements (Listing 9.45): DATA lr_interactive_form TYPE REF TO cl_wd_interactive_form. lr_interactive_form = cl_wd_interactive_form=>new_interactive_form( id = 'IFO_NON_INTERACTIVE' view = view bind_data_source = 'DATASOURCE' bind_pdf_source = 'PDFSOURCE' template_source = 'YADOBE' display_type = cl_wd_interactive_form=>e_display_type-native enabled = abap_false width = '400px' height = '500px' ).
Listing 9.45 Dynamic creation of an InteractiveForm UI element
9.6 Integration
9.6.2
215
FileUpload
We can use this UI element to upload a file from the client to the server. Hereunder, we present a list with some of the FileUpload properties that can be bound, and the attribute type in case the property is bindable (Table 9.30). Table 9.30 Some of the FileUpload UI element properties Name Type Initial value Data XSTRING fileName STRING mimeType STRING
Bindable Mandatory Yes Yes
We create a very simple example – uploading to the server a text file that contains the numbers from 1 to 10 and then displaying the file content in a browser window. Figure 9.127 shows the structure of the test.txt file created on the Desktop by using Notepad.
Fig. 9.127 File structure
We create a WD Component with a view named V_VIEW. In the view context, we create four attributes: FILECONTENT of XSTRING type required to hold the file content, FILENAME of STRING type required to hold the name of the upload file, MIMETYPE of STRING type required to hold the mime type of the upload file and SIZE of INTEGER type required to hold the file size, in bytes. The WD component structure and the view context structure are presented in Fig. 9.128.
Fig. 9.128 WD component structure and view context structure
216
9 User Interface Elements (UI elements), Static and Dynamic Programming
Onto the view V_VIEW, we insert a FileUpload UI element. This UI element doesn’t have an action attached. To upload the file, we need to add an UI element from the action category, in our case a Button. As we have seen, the mandatory property of this UI element is DATA. For this UI element, we must realise a data binding to the attribute of XSTRING type (FILECONTENT). The View layout is presented in Fig. 9.129.
Fig. 9.129 View Layout
The FileUpload UI element has an input field, where we have to write the directory path and the file name we want to upload to the server, and a button that offers the possibility to search for a file. In case we search for a file by using this button, the fully qualified path is written in the input field. When the user presses the Upload button, the file content is loaded into the XSTRING attribute. With the help of the onactionupload event handler method, we calculate the file size by using the XSTRLEN length function. Listing 9.46 shows the structure of this method. METHOD onactionupload. DATA lv_content TYPE xstring. DATA lv_size TYPE i. wd_context->get_attribute( EXPORTING name = 'FILECONTENT' IMPORTING value = lv_content ). lv_size = XSTRLEN( lv_content ). wd_context->set_attribute( name = 'SIZE' value = lv_size ). ENDMETHOD.
Listing 9.46 The onactionupload event handler method
9.6 Integration
217
When the user presses the Show button, the Framework triggers the event handler method onactionshow (Listing 9.47).
METHOD onactionshow. DATA: lv_content TYPE xstring, lv_mimetype TYPE string, lv_size TYPE i, lv_filename TYPE string. wd_context-> get_attribute( EXPORTING name = 'FILECONTENT' IMPORTING value = lv_content ). wd_context-> get_attribute( EXPORTING name = 'FILENAME' IMPORTING value = lv_filename ). wd_context-> get_attribute( EXPORTING name = 'MIMETYPE' IMPORTING value = lv_mimetype ). wd_context-> get_attribute( EXPORTING name = 'SIZE' IMPORTING value = lv_size ). cl_wd_runtime_services=>attach_file_to_response( i_filename = lv_filename i_content = lv_content i_mime_type = lv_mimetype i_in_new_window = abap_true i_inplace = abap_true ). ENDMETHOD.
Listing 9.47 The onactionshow event handler method
As we can see, we have used the static public method ATTACH_FILE_TO_ RESPONSE of the CL_WD_RUNTIME_SERVICES, required to add a file to a response. This method has the following parameters: I_FILENAME (the name of the file), I_CONTENT (the content of the file in XSTRING format), I_MIME_ TYPE (the mime type of the file), I_IN_NEW_WINDOW (parameter of Boolean type that specifies if the file content will be displayed in a new window) and I_INPLACE (of the same Boolean type). By using the Delete button, we can delete the data from the context. In case we don’t delete these data, the file would be kept in the memory until a new file is uploaded or until we complete the application. The runtime structure is presented in Fig. 9.130.
9.6.2.1
Dynamic Programming
RUNTIME CLASS: CL_WD_FILE_UPLOAD Hereunder, we present a table showing the correspondence between the view designer name and the runtime name, with the proper types, in case of dynamic programming of a FileUpload UI element (Table 9.31).
218
9 User Interface Elements (UI elements), Static and Dynamic Programming
Fig. 9.130 Runtime
Table 9.31 Dynamic programming View designer name Data fileName mimeType
Runtime name DATA FILE_NAME MIME_TYPE
Type XSTRING STRING STRING
The implementation of a dynamic FileUpload UI element contains the following statements (Listing 9.48):
DATA lr_file_upload TYPE REF TO cl_wd_file_upload. lr_file_upload = cl_wd_file_upload=>new_file_upload( id = 'FILEUPLOAD' bind_data = 'FILECONTENT' bind_file_name = 'FILENAME' bind_mime_type = 'MIMETYPE' ).
Listing 9.48 Dynamic creation of a FileUpload UI element
9.6 Integration
219
To obtain more information regarding the execution time required for some ABAP code parts, advises and certain tips and tricks for the ABAP Objects (e.g. ABAP Objects performance examples), we can use the SM30 transaction (ABAP Objects Runtime Analysis). Tip The appearance of the UI elements can be influenced by using themes. These ones can be used either for applications that run in the SAP NetWeaver Portal, or for stand alone applications
Chapter 10
Messages, Exceptions and Web Dynpro ABAP
“If we can really understand the problem, the answer will come out of it, because the answer is not separate from the problem.” Jiddu Krishnamurti
Abstract This chapter shows how to work with exceptions and messages within the Web Dynpro ABAP applications. For each of the two variants (messages and exceptions), we present two possible implementation scenarios. Therefore, we start with the modality to create the texts of messages and exceptions, and we conclude with the modality of using them for the created applications. A good user interface catches exceptions, describes the errors that occur and displays messages that contain information for the application end user. As we have already seen, Web Dynpro offers the interface, through the IF_WD_MESSAGE_MANAGER, as a manager for messages. This interface has many methods we can choose to create messages. For example: l l
l
l
l l l
REPORT_T100_MESSAGE – reports a message by using a T100 input REPORT_ERROR_MESSAGE – reports a Web Dynpro message with optional parameters REPORT_ATTRIBUTE_T100_MESSAGE – reports a Web Dynpro exception for a Context Attribute REPORT_ATTRIBUTE_ERROR_MESSAGE – reports a Web Dynpro exception for a Context Attribute REPORT_SUCCESS – reports a success message REPORT_WARNING – reports a warning message REPORT_EXCEPTION – reports a Web Dynpro exception
The methods with REPORT_ATTRIBUTE_XXX or REPORT_ELEMENT_ XXX can be used to connect the message with the UI element that has generated that message. Until now, we have created only simple messages that contained text introduced in coding. This art of programming isn’t recommended for many reasons, e.g. the U. Gellert and A.D. Cristea, Web Dynpro ABAP for Practitioners, DOI 10.1007/978-3-642-11385-7_10, # Springer-Verlag Berlin Heidelberg 2010
221
222
10 Messages, Exceptions and Web Dynpro ABAP
message text inserted in coding cannot be translated without re-coding. In this chapter, we will create messages by using assistance class, T100 table, exception class and message class.
10.1
Message Handling
The messages that we display in Web Dynpro applications can be created in many ways. For example, we can create messages: l l
As dynamic texts – stored in the text pool of the assistance class As texts from database table T100 It is not recommendable to enter specific language text in coding.
10.1.1
Dynamic Texts Stored in the Text Pool of the Assistance Class
One of the most important functions of the assistance classes is the management of the dynamic texts. In the Web Dynpro ABAP, the CL_WD_COMPONENT_ ASSISTANCE class provides central functions through which a WD component can access text symbols of the assistance class. We create a WD component, a registration form for a user. The component structure is presented in Fig. 10.1.
Fig. 10.1 WD component structure
The user has to fill a registration form with two mandatory fields: name and date of birth. If the user fills the form with the requested data, we show an information message to inform him that the data are saved. If the user doesn’t fill a mandatory field, we show an error message. The layout and the context node are presented in Fig. 10.2. To be able to work with dynamic texts stored in the text pool of the assistance class, we have to firstly create an assistance class. We can use class builder, Transaction SE24, to create a usual ABAP class. An Assistance class is a usual ABAP class that inherits from the super-class CL_WD_COMPONENT_ASSISTANCE. This super-class provides to our YCL_ASSISTANCECLASS class two additional methods (Fig. 10.3).
10.1 Message Handling
223
Fig. 10.2 The Layout and the context node
Fig. 10.3 Creation of an assistance class
To maintain text symbols in the assistance class, we choose from the Assistance Class Maintenance menu Goto -> Text Elements. Each new text symbol has an identification symbol (a three-digit ID) and a corresponding text (Fig. 10.4).
Fig. 10.4 Text symbols
To be able to have access to the text symbols of the assistance class by using the instance attribute WD_ASSIST, we have to assign the assistance class to our component. For each Web Dynpro component, we can create only a uniquely assigned assistance class (Fig. 10.5).
224
10 Messages, Exceptions and Web Dynpro ABAP
Fig. 10.5 Assistance class assigned to a WD component
When the user presses the REGISTRATION button, the Framework triggers the event handler method onactionregistration (Listing 10.1). METHOD onactionregistration. DATA: text_success TYPE string, text_error TYPE string.
text_error = wd_assist->if_wd_component_assistance~get_text( key = '001'). text_success = wd_assist->if_wd_component_assistance~get_text( key = '002' ). DATA: lr_node TYPE REF TO if_wd_context_node, lv_name TYPE string, lv_dateofbirth TYPE ydateofbirth. lr_node = wd_context->get_child_node( 'PERSON' ). lr_node->get_attribute( EXPORTING name = 'NAME' IMPORTING value = lv_name ). lr_node->get_attribute( EXPORTING name = 'DATEOFBIRTH' IMPORTING value = lv_dateofbirth ). DATA lr_api_controller TYPE REF TO if_wd_controller. DATA lr_message_manager TYPE REF TO if_wd_message_manager. lr_api_controller ?= wd_this->wd_get_api( ). lr_message_manager = lr_api_controller->get_message_manager( ). IF lv_name IS INITIAL OR lv_dateofbirth IS INITIAL. lr_message_manager->report_error_message( message_text = text_error ). ELSE. lr_message_manager->report_success( message_text = text_success ). ENDIF. ENDMETHOD.
Listing 10.1 Coding of event handler method
To have access to the text symbols of the assistance class, we have to create a local variable of STRING type (text_success TYPE string). At runtime, when the method if_wd_component_assistanceget_text is called, the ID is passed to the KEY parameter, and the corresponding text symbol is stored into the local variable of STRING type. DATA: text_success TYPE string. text_success = wd_assist->if_wd_component_assistanceget_text( key =‘002’ ). To access the text from an assistance class, we can use the Web Dynpro Code Wizard (Fig. 10.6).
10.1 Message Handling
225
Fig. 10.6 Web Dynpro code wizard
If the attributes name or dateofbirth are empty, we show an error message by using the report_error_message method. If not, we show an information message by using the report_success method. In Fig. 10.7 we present the execution result.
Fig. 10.7 Application result
10.1.2
Text from Database Table T100
We can create messages by using message maintenance – transaction SE91 (Fig. 10.8).
Fig. 10.8 Message class YCL_T100_MESSAGE
226
10 Messages, Exceptions and Web Dynpro ABAP
The Messages created here are stored in the database table T100. This table has the following columns: message number – MSGNR, short text – TEXT, language key – SPRSL and message class – ARBGB (Fig. 10.9).
Fig. 10.9 The structure of the T100 table
We can search in this table to find all the messages with number 000, language English and all the texts that begin with the word “The”. After this search, we find also our message, too (Fig. 10.10).
Fig. 10.10 Searching for a message in T100 table
We create the same WD component, but in this case we use messages with text from the database table T100. When the user presses the REGISTRATION button, the Framework triggers the event handler method onactionregistration (Listing 10.2). If the attributes NAME or DATEFOFBIRTH are empty, we show an error message by using the report_t100_message method. Msgty represents the message type E – error, msgid represents the name of the message class and msgno represents the message ID (a three-digit number).
10.2 Exception Handling
227
METHOD onactionregistration. DATA: lr_node TYPE REF TO if_wd_context_node, lv_name TYPE string, lv_dateofbirth TYPE ydateofbirth. lr_node = wd_context->get_child_node( 'PERSON' ). lr_node->get_attribute( EXPORTING name = 'NAME' IMPORTING value = lv_name ). lr_node->get_attribute( EXPORTING name = 'DATEOFBIRTH' IMPORTING value = lv_dateofbirth ). DATA lr_api_controller TYPE REF TO if_wd_controller. DATA lr_message_manager TYPE REF TO if_wd_message_manager.
lr_api_controller ?= wd_this->wd_get_api( ). lr_message_manager = lr_api_controller->get_message_manager( ). IF lv_name IS INITIAL OR lv_dateofbirth IS INITIAL. lr_message_manager->report_t100_message( msgid = 'YCL_T100_MESSAGE' msgno = '000' msgty = 'E'). ELSE. lr_message_manager->report_t100_message( msgid = 'YCL_T100_MESSAGE' msgno = '001' msgty = 'I'). ENDIF. ENDMETHOD.
Listing 10.2 Coding of event handler method
If the attributes name or dateofbirth are not empty, we show an information message type I. At runtime, the User Interface is the same as for the latest example (Fig. 10.6). The only difference is the way we have created these messages.
10.2
Exception Handling
Exceptions can be raised by the ABAP runtime environment, or explicitly in coding. Exception situations have many causes (e.g. cardinality violation for a context node). The exceptions are treatable or untreatable; all the unhandled exceptions cause a runtime error, a so-called short dump. We can find all the short dumps from the system with transaction ST22, ABAP runtime error (Fig. 10.11). We can find the runtime error from today and yesterday by using the two buttons “Today” and “Yesterday”, or we can search for a specific runtime error by using our selected parameters.
228
10 Messages, Exceptions and Web Dynpro ABAP
Fig. 10.11 ABAP runtime error
Web Dynpro ABAP offers support to work with the exception classes through the methods of the Message Manager. Each exception has an explanatory text assigned to it that describes the exception. It can be an Online Text Repository OTR or a text from a message class. We can create our own exception classes as global classes by using Class Builder or the local classes in our programms. Class-based exception handling is based on the exception classes; we have a notation specification for an exception class: its name has to begin with cx, zcx or ycx. As basic exception classes, we have CX_STATIC_CHECK, CX_DYNAMIC_ CHECK and CX_NO_CHECK. This classes are derived from the superclass CX_ROOT.
10.2.1
Exception Class with OTR Text
We create a WD component with the structure presented in Fig. 10.12.
Fig. 10.12 WD component structure
10.2 Exception Handling
229
By using the view V_VIEW, we implement a search mask. The user enters the concurrent ID and receives more information about him. All the data about candidates are stored in the database table YPERSON we have created in the ABAP Dictionary. When we don’t find in the database a concurrent with the searched ID, we raise an exception and we show a proper message. The view layout is presented in Fig. 10.13.
Fig. 10.13 View layout
The context has the structure presented in Fig. 10.14.
Fig. 10.14 Context structure
We have defined a node Search (Singleton, Cardinality 1. . .1) that holds the child node PERSON and the attribute ID_PERSON. The attribute ID_PERSON has the type yperson-id_person, Input help mode Automatic. For this table field, we have assigned in the ABAP Dictionary the search help YSH_ID_PERSON. We use this attribute to hold the concurrent ID entered by the user in the search mask. The child node PERSON (Singleton, Cardinality 0. . .1) has the dictionary structure YPERSON, and as attributes we have quickly almost the entire table fields (without id_person). We use this context node to hold all the concurrent data with the searched ID. To show the result information, we have created a data binding between this node and the Table UI Element. The user enters an ID and presses the button SEARCH. If the concurrent with this ID exists in the database table YPERSON, we show in the UI Element table the proper information, otherwise we raise an exception and the corresponding error message is shown. Before working with exception messages, we have to create an exception class (Fig. 10.15).
230
10 Messages, Exceptions and Web Dynpro ABAP
Fig. 10.15 Creating an exception class
As can be seen, we create an exception class without message class. In this case, the OTR is used as a central storage area for the exception texts. In the Text tab, we create an exception text “The candidate with ID: &id_candidate& doesn’t exist!”, with the ID: YCX_NO_CANDIDATE (Fig. 10.16).
Fig. 10.16 Defining exception texts
Each exception text we create in the Texts tab consists of an ID and a corresponding text. The placeholder &id_candidate& is replaced at runtime by the content of the attribute with the same name defined in the Attributes tab (Fig. 10.17).
10.2 Exception Handling
231
Fig. 10.17 Defining attributes
When the user presses the SEARCH button, the Framework triggers the event handler method onactionsearch (Listing 10.3).
METHOD onactionsearch . DATA obj TYPE REF TO ycx_exception_otr_txt. DATA: lt_candidate TYPE TABLE OF yperson, lr_node TYPE REF TO if_wd_context_node, ls_data TYPE if_v_view=>element_search, lv_id_person TYPE yperson-id_person. lr_node = wd_context->get_child_node( 'SEARCH' ). lr_node->get_attribute( EXPORTING name = 'ID_PERSON' IMPORTING value = lv_id_person ). TRY. SELECT * FROM yperson INTO TABLE lt_candidate WHERE id_person = lv_id_person. IF sy-subrc = 0. DATA lr_subnode TYPE REF TO if_wd_context_node. lr_subnode = lr_node->get_child_node( 'PERSON' ). lr_subnode->bind_table( new_items = lt_candidate ). ELSE. RAISE EXCEPTION TYPE ycx_exception_otr_txt EXPORTING textid = ycx_exception_otr_txt=>ycx_no_candidate id_candidate = lv_id_person. ENDIF. CATCH ycx_exception_otr_txt INTO obj. DATA lr_api_controller TYPE REF TO if_wd_controller. DATA lr_message_manager TYPE REF TO if_wd_message_manager. lr_api_controller ?= wd_this->wd_get_api( ). lr_message_manager = lr_api_controller->get_message_manager( ). lr_message_manager->report_exception( message_object = obj ). ENDTRY. ENDMETHOD.
Listing 10.3 Coding of event handler method
After defining the data, we pass the value of the attribute id_person in the local variable lv_id_person. By using the TRY – ENDTRY control structure, we handle a possible exception that can occur. We use open SQL to select all the data from the
232
10 Messages, Exceptions and Web Dynpro ABAP
database table YPERSON into the internal table lt_candidate, where the field id_person is the same with our searched ID. If we find this record in our database table, we populate the child node PERSON, because no exception occurs in the TRY block and the system continues the processing after ENDTRY. Otherwise, a class-based exception occurs in the TRY block and the system searches for an exception handler. With RAISE EXCEPTION, we can raise an exception explicitly from our WD method. RAISE EXCEPTION TYPE ycx_exception_otr_txt EXPORTING textid = ycx_exception_otr_txt=>ycx_no_candidate id_candidate = lv_id_person. This exception is caught in the CATCH block of the same TRY control structure: CATCH ycx_exception_otr_txt INTO obj. Because the additional INTO is specified, a reference to the exception object is stored in obj, where obj is the object reference variable. After this, we use the method REPORT_EXCEPTION of the IF_WD_MESSAGE_MANAGER interface to report a WD exception. In Fig. 10.18, we present the execution result. The first picture represents the runtime where the exception occurs in the TRY-ENDTRY control structure, and the
Fig. 10.18 Application result
10.2 Exception Handling
233
second picture represents the case when no exception occurs. In the second scenario, we can show, in the same time, the result of the Search help created in the ABAP Dictionary and attached to the id_person field of our database table YPERSON.
10.2.2
Exception Class with Text from a Message Class
We create the same WD component, but in this case we use an exception class with text from a message class. In this case, the interface IF_T100_MESSAGE is automatically included in the class definition. Figure 10.19 shows the creation of an exception class by using Message Class.
Fig. 10.19 Creating an exception class
We firstly create a message class (Fig. 10.20).
Fig. 10.20 Message class
In the “Properties” tab of the exception class, we have to enter the name of the message class we use (Fig. 10.21).
234
10 Messages, Exceptions and Web Dynpro ABAP
Fig. 10.21 Message class assignment
We create the same ID_CANDIDATE attribute in the tab Attributes (Fig. 10.22).
Fig. 10.22 Class attributes
Each exception ID can be mapped to a message class and message ID. To do this, we have to use the Button Message Text (Fig. 10.23). We assign the exception class attribute ID_CANDIDATE to the message class YCL_T100_MSG, message number 000. The placeholder and is replaced at runtime by the content of the ID_CANDIDATE attribute. After activation, we can use this exception class in our WD component. Exception texts based on message classes are basically used in the same way as the exception texts that use OTR texts. When the user presses the SEARCH button, the Framework triggers the event handler method onactionsearch that has the same structure as the Listing 10.3. The only modification we have to do is to change the name of the exception class raised when an exception occurs (Listing 10.4).
10.2 Exception Handling
235
Fig. 10.23 Assigning attributes of an exception class to a message
Listing 10.4 Exception handling
DATA obj TYPE REF TO ycx_exception_t100_txt. …………. RAISE EXCEPTION TYPE ycx_exception_t100_txt EXPORTING textid = ycx_exception_t100_txt=>ycx_no_candidate id_candidate = lv_id_person. ………. CATCH ycx_exception_t100_txt INTO obj. ………
Chapter 11
Writing Multilanguage Applications
“If you talk to a man in a language he understands, that goes to his head. If you talk to him in his language, that goes to his heart.” Nelson Mandela
Abstract This chapter mainly focuses on the creation of Multilanguage applications. So, the applications we realize are going to be easily internationalized without being necessary to recode them, but only to translate some centralized strings. For this, we have to respect some rules, as follows: using the tools offered by the ABAP Workbench, establishing an initial language for our project, and avoiding to enter language specific texts in the codification of the business logic. Internationalization (I18N) is a need for the global business software. In this chapter, we will see some of the tools offered by the ABAP Workbench to create Multilanguage User Interface and the tools we can use to make Multilanguage records in the database. When the user logs onto the SAP System, he should enter a log-on language. If he doesn’t enter a language, then it is used the default log-on language from the user account (Fig. 11.1) Transaction SU01.
Fig. 11.1 Log-on language
U. Gellert and A.D. Cristea, Web Dynpro ABAP for Practitioners, DOI 10.1007/978-3-642-11385-7_11, # Springer-Verlag Berlin Heidelberg 2010
237
238
11 Writing Multilanguage Applications
This is the language in which the Web Dynpro application (and all others development objects) is originally written and the language that the System uses after logging-on. A list with all the languages installed in the system we can find by using the transaction SMLT – Language Management (Fig. 11.2).
Fig. 11.2 Transaction language management
In our case, we can use English, German or Russian as original log-on language, and we can translate our application from the original language into another one. Tip It is advisable that all the created repository objects, required into a project, to be created in the same language initially established in the project. So we can avoid, for example, the elements required for the back-end to be created in English, the elements required for the web interface to be created in German, and so on. For more information about this topic, advantages, disadvantages and tricks used to well program the ABAP, please refer to SAP book: Official ABAP Programming Guidelines (Keller et al.).
ABAP Workbench offers many tools that simplify the process of creating internationalized applications. So, we create WD applications that support multiple languages without re-designing or modifying. As mentioned above, an internationalized application doesn’t contain languagespecific text elements in the source text. As language-specific texts, we can mention: l
l l
Texts used, for example, to label UI elements or required for the dynamic programming, etc. Texts defined when creating development objects in the ABAP Dictionary Messages
11.1
Creating Multilanguage User Interfaces
We create a simple WD component, where we use some of the above-mentioned tools to offer support for English and German without making any code changes. All we have to do is to translate certain centralised strings and, after changing the
11.1 Creating Multilanguage User Interfaces
239
log-on language (in our case, from “en” to “de”), the data will be automatically shown in the respective language. The WD component structure is presented in Fig. 11.3. Fig. 11.3 WD component structure
In the context view, we create a context node named PERSON, Cardinality 1. . .1, Singleton, dictionary structure YPERSON and a context attribute named TEXT_I18N of STRING type. The context view and the view layout are presented in Fig. 11.4.
Fig. 11.4 Context node and view layout
We didn’t insert any static strings for the “text” property of the UI elements Label and Button, or for the Caption view element. The strings shown as labels for the InputField UI elements represent the texts from the label field of the elementary data elements created in the ABAP Dictionary. For example, the label with the ID “FIRSTNAME_LBL” represents the label for the InputField bound to the attribute FIRSTNAME. The data element for this attribute is YPERSON-FIRSTNAME. If we look in our table definition, we can see that the elementary data type is YFIRSTNAME. In Fig. 11.5, it can be seen that “text” property of the label FIRSTNAME_LBL doesn’t contain any static values. To establish this string, we
240
11 Writing Multilanguage Applications
use the text with the length Medium, defined in the YFIRSTNAME data element, i.e. “First Name”.
Fig. 11.5 Text property and elementary data elements
11.1.1
Internationalization of Data Elements Defined in ABAP Dictionary
To internationalized data element defined in ABAP Dictionary, we have to translate the corresponding texts. Figure 11.6 shows the way we can perform this translations.
Fig. 11.6 Translating the texts from a data element
After this, a pop-up window asks the language in which we want to translate the texts. We choose German and we enter the texts to be translated, for the strings (Fig. 11.7). We repeat the same steps, until all the strings for the corresponding elementary data elements are translated.
11.1 Creating Multilanguage User Interfaces
241
Fig. 11.7 Translating the strings
11.1.2
Internationalization of Domains Defined in ABAP Dictionary
Similarly, we translate the texts stored in our Domain Y_COUNTRY_DOMAIN (Fig. 11.8).
Fig. 11.8 English – German translation for a domain
242
11 Writing Multilanguage Applications
Figure 11.9 shows the translation of the fixed values for the Domain.
Fig. 11.9 Translating the domain fixed values
11.1.3
Internationalization of Text from OTR
In our example, we have to enter a value in the text property of the UI element Button. To do this, we choose the OTR text that exists in the SOTR_VOCABULARY_ BASIC package (Fig. 11.10).
Fig. 11.10 The OTR text from the SOTR_VOCABULARY_BASIC package
11.1 Creating Multilanguage User Interfaces
243
To create our own OTR text, we can use the menu Goto ! Online Text Repository Browser or the transaction SOTR_EDIT Editor for OTR texts. Figure 11.11 shows how we can create an OTR text by using the Online Text Repository Browser.
Fig. 11.11 Creating OTR texts
The basic vocabulary stored in the SOTR_VOCABULARY_BASIC package can be used for all the packages, but the created OTR texts are stored only once per each package (Fig. 11.12).
Fig. 11.12 Our own-defined OTR text
To translate an OTR text, we can use the transaction SE63 Translation: Original Screen.
244
11 Writing Multilanguage Applications
After translating it, we can use our own defined OTR text in the same way as the OTR texts defined by SAP in the SOTR_VOCABULARY_BASIC package. Then, we have to create a Multilanguage text for the text property of the Caption element.
11.1.4
Internationalization of Text from Assistance Class
In the previous chapter, we have seen how we can use an Assistant Class to work with messages. In this case, we use the texts stored in the text pool of the assistance class to make Multilanguage our text required by the Caption view element. We create an assistance class named YCL_I18N. We define here the text to be made Multilanguage (Fig. 11.13).
Fig. 11.13 Texts from assistance class
In the field mLen, we have to specify the maximum length of the text string of a text symbol. As we have already seen, this value should be greater than or equal to the defined length (dLen). It is better to use a higher value, because, at design time, we don’t know for how many languages we offer support. In English, for example, the length is 36, but when we translate this string in another language, it might be greater. In this case, we could not be able to enter the entire translation text. This length is saved in the text pool. To translate this text from English into German, we use the menu Goto ! Translation (Fig. 11.14).
Fig. 11.14 Translating texts from the assistance class
11.1 Creating Multilanguage User Interfaces
245
After this, we realise a data binding between the attribute TEXT_I18N and the property text of the Caption element. We dynamically access the string we have just defined and translated (Listing 11.1). METHOD wddoinit . DATA: lv_text TYPE
string. lv_text = wd_assist->if_wd_component_assistance~get_text( '001' ). wd_context->set_attribute( name = 'TEXT_I18N' value = lv_text ).
ENDMETHOD
Listing 11.1 wdDoInit( ) Hook method
As we have mentioned above, to be able to have access to the text symbols of the assistance class by using the instance attribute WD_ASSIST, we have to assign the assistance class to our component. After this, we run our application (Fig. 11.15).
Fig. 11.15 Runtime. Default language: English
We change the language into German (de) (Fig. 11.16).
11.1.5
Internationalization of Messages
We create a Message class named YCL_I18N_MSG, where we define a message with the ID “000” and the short text “First Name is required!” We want to show this message when the user presses the Update button.
246
11 Writing Multilanguage Applications
Fig. 11.16 Runtime – German
To translate this message, we choose from MENU Goto ! translation (Fig. 11.17).
Fig. 11.17 Translating a short text in the message class
When the user presses the Upload button, the Framework triggers the event handler method onactionsave (Listing 11.2). We run our application in the original language English and in German (Fig. 11.18).
11.2 Multilanguage Records in the Database
247
METHOD onactionsave. DATA: lr_api_controller TYPE REF TO
if_wd_controller, lr_message_manager TYPE REF TO if_wd_message_manager. lr_api_controller ?= wd_this->wd_get_api( ). lr_message_manager = lr_api_controller->get_message_manager( ). lr_message_manager->report_t100_message( msgid = 'YCL_I18N_MSG' msgno = '000' msgty = 'E'). ENDMETHOD.
Listing 11.2 The onactionsave event handler method
Fig. 11.18 Multilanguage messages
Tip As we have seen in the presented examples, to translate texts we usually use: GoTo ! Translation In the same way, we can translate either long or short texts from Adobe Forms. In this case, we need to have shown the form for which we are going to realize the translation in Adobe LiveCycle Designer.
11.2
Multilanguage Records in the Database
In this case, we make Multilanguage the records we store in a database table. We create a very simple example to show how we can store data in a database table, not only in the log-on language, and then we create the User Interface in Web Dynpro to see how we can process these data.
248
11 Writing Multilanguage Applications
We copy the table YEU_COUNTRIES and rename it YEU_I18N. Our target is to be able to store the political system for each EU Country not only in English, but in German, too.
11.2.1
Study an Example Created in the System
Before creating our own example, we shall briefly explain the table structure we are going to build. In this respect, we study a simple example presented in the system, starting with the search of a text table. A text table usually has the suffix T and contains an explanatory text in several languages, for each key. With the transaction SE11, we display all the tables that end in “_T” (Fig. 11.19).
Fig. 11.19 Searching to find a text table
From the list that appears, we choose to see the structure of the text table for Text Table for Release/Lock object Handling (Fig. 11.20). As we can see, we have a Field named SPRAS of SPRAS type that represents the Language Key and two fields BEZ (description) and KURZBEZ (short description) that contain an explanatory text in several languages, for each FSOBJANL key. In this case, we have support for German and English, so we have the translation in two languages (E – English, D – German) for each key (Fig. 11.21). Let’s look at the foreign key relationship: (Fig. 11.22). As we can see, this table is a text table for the table /BEV3/CHCTFSOS The structure of this table is presented in Fig. 11.23. The table /BEV3/CHCFSOS_T is a text table for /BEV3/CHCTFSOS. If we study both tables, we see that the text table additionally contains a language key
11.2 Multilanguage Records in the Database
Fig. 11.20 Text table structure
Fig. 11.21 The content of a text table
Fig. 11.22 Foreign key relationship
249
250
11 Writing Multilanguage Applications
Fig. 11.23 Table /BEV3/CHCFSOS
field and two extra Fields that contain an explanatory text in English and in German, for each key entry of /BEV3/CHCTFSOS. Let’s look at the structure of the table /BEV3/CHCFSOBJS: (Fig. 11.24).
Fig. 11.24 Structure of the table /BEV3/CHCFSOBJS
For our purpose, in this case it is interesting the Field FSOBJANL. As we can see, this field has an foreign key defined to /BEV3/CHCTFSOS.
11.2.2
Creating Table Structures and Internationalization of the Records
For our example, we create the same structure as the one presented above, but with only one explanatory text for the politicalsystem per each EU Country. The table YEU_I18N has the structure presented in Fig. 11.25.
11.2 Multilanguage Records in the Database
251
Fig. 11.25 YEU_I18N table
The Field POLITICALSYSTEM has defined an foreign key to the table YKEY that holds only the ID of the politicalsystem (Fig. 11.26).
Fig. 11.26 Key table
The text table has the structure presented in Fig. 11.27.
Fig. 11.27 Text table
To link the politicalsystem key with the descriptions included in the text table, we have to link the table YKEY_T with the table YKEY by using a foreign key (Fig. 11.28).
252
11 Writing Multilanguage Applications
Fig. 11.28 Foreign key
Now, we have to maintain the data that refer to an object and are technically distributed between the tables YKEY and YKEY_T (Fig. 11.29).
Entry
Maintenance View
Fig. 11.29 Maintaining data in the tables YKEY and YKEY_T
To realize this, we create a Maintenance View (Fig. 11.30). Call transaction SE11, enter the name of the new maintenance view in the field VIEW and press CREATE. At the next popup window choose the kind of view we want to create. In our case “Maintenance View”. Enter the tablenames as shown below and press button “Relationships”. In our case we can accept the suggestion. The View Fields are presented in Fig. 11.31. After this, we choose from the menu Utilities ! Table Maintenance Generator, to generate table maintenance (Fig. 11.32).
11.2 Multilanguage Records in the Database
Fig. 11.30 Maintenance view
Fig. 11.31 View fields
Fig. 11.32 Generating maintenance view
253
254
11 Writing Multilanguage Applications
We go back to the Maintenance View and we choose from the menu Utilities ! Contents (Fig. 11.33).
Fig. 11.33 Insert content
By using the New Entry button, we can insert new records (Fig. 11.34).
Fig. 11.34 New entries
We insert three political systems and then we translate them in German. To do this, we select the entry we want to translate and we choose from the menu Goto ! Translation (Fig. 11.35).
11.2 Multilanguage Records in the Database
255
Fig. 11.35 Translating records
In this way, we translate all the records.
11.2.3
Using the Internationalized Records in WebDynpro
Through a Web Dynpro application, we create a mini-administration User Interface for our table YEU_I18N. The view layout and the context node are presented in Fig. 11.36.
Fig. 11.36 View layout and context node
The context node has the dictionary structure YEU_I18N. The runtime result is presented in Fig. 11.37.
256
11 Writing Multilanguage Applications
Fig. 11.37 Internationalization – database records
To select the values from the database according to the log-on language, we create a database view in the ABAP Dictionary and perform a selection, where spras ¼ sy-langu: SELECT * FROM y_i18nv INTO TABLE lt_i18nv WHERE spras ¼ sy-langu. We create a context node named I18NSELECT that has, as dictionary structure the view “Y_I18NV” that we have created in the ABAP Dictionary (Fig. 11.38).
Fig. 11.38 Database view and context node
11.2 Multilanguage Records in the Database
The runtime result is presented in Fig. 11.39.
Fig. 11.39 Runtime
257
Chapter 12
Web Dynpro Model
“Always do your best. What you plant now, you will harvest later” Og Mandino
Abstract This chapter presents the role of a model in a multicomponent Web Dynpro application, showing not only the modality to use such a model, but also to create it. We are going to focus on three types of models: Assistance class, BAPI and Web Service. So far, we have created only small applications used to access the data contained in a table, through the SQL statements introduced in the methods defined in the views. This art of programming is not in concordance with the MVC design pattern. According to the Model View Controller MVC paradigm, the application data and their user interface are separated. The Model represents the business logic, the View represents the user interface and the controller has certain responsibilities, as the communication between the model and the view, or data processing at runtime. In this way, it is possible to change the user interface without changing the business logic, or it is possible to change the business logic without having to change the user interface. In the same time, we can reuse the same business logic for more user interfaces. In the Web Dynpro ABAP, the model can be implemented by the: l l l l
Assistance class BAPI WebService Faceless Component, etc.
A Web Service can be compared with a “black box” that offers certain functionalities. These functionalities can be integrated in a client application (in our case, Web dynpro ABAP) that consumes the respective web service. In this respect, a Web Service may require certain inputs from the client application and delivers it the proper answer. Usually, Web Services are used to communicate between different platforms. As mentioned before, an assistance class is a normal ABAP class that inherits from the CL_WD_COMPONENT_ASSISTANCE. Each Web Dynpro U. Gellert and A.D. Cristea, Web Dynpro ABAP for Practitioners, DOI 10.1007/978-3-642-11385-7_12, # Springer-Verlag Berlin Heidelberg 2010
259
260
12 Web Dynpro Model
component can have a uniquely assigned assistance class that offers certain benefits, as follows: l l
It works with text symbols It’s more advantageous to call its methods than to call the methods defined in a Web Dynpro controller.
The Business Application Program Interfaces (BAPI) are specific methods for business object types that offer the possibility to access external data and processes. The Faceless Component is a Web Dynpro Component that doesn’t have any View or Window; in conclusion, it’s a Component that doesn’t have any User Interface, but it encapsulates functionality and can be used to build a Model.
12.1
Assistance Class as a Model for a Multicomponent Application
Essentially, each ABAP class can be used as a model. The particularity of an assistance classes is that we can assign it to a Web Dynpro component and it is automatically instantiated when the proper component is called. We create an assistance class named YCL_AC_MODEL (Fig. 12.1).
Fig. 12.1 Assistance class
In this assistance class, we create three methods named SEARCH_CANDIDAT, SELECT_CANDIDATE and INSERT_CANDIDATE (Fig. 12.2). Here, we store the
Fig. 12.2 Methods for the assistance class
12.1 Assistance Class as a Model for a Multicomponent Application
261
coding required within the WD components to look for a candidate, to select all the candidates and to insert information about a candidate into or from the database table YPERSON. Before implementing our methods, we created the lowest level of coding that abstracts the data access. In this case, we choose to implement the simplest data access method by using the classical ABAP tools, respective through the Function Modules, but we can also use other tools, e.g. the Persistent Object Classes, required to benefit of the object oriented programming (OOP). In case we want to use Persistent Objects to access the data from the database table in the Object Oriented mode, we can use for our Web Dynpro project the same structure (by taking the Assistance class as a model). But, in this case, we have to replace the Function Modules with Persistent Classes. Tip For more details about Persistent Objects in ABAP, please refer to the SAP Press Book: Object Services in ABAP (Christian Assig et al.)
One of the created Function Modules will be used later, as the end point for a BAPI. It will be also used to create a Web Service. A Function Module (FM) is a procedure with public interface, which can be created within a Function Group. To create a Function Group, we select Create ! Function Group from the context menu of our package name. We create a Function Group named YFG_DBACCESS. Here, we implement three FMs, named YFM_SEARCH_ CANDIDATE, YFM_SELECT_CANDIDATE and YFM_ INSERT_CANDIDATE. Listing 12.1 shows the implementation of YFM_SEARCH_CANDIDATE. The exception class YCX_EXCEPTION_T100_TXT was defined hereinbefore, when we have seen how we can work with the exception classes in WD. FUNCTION YFM_SEARCH_CANDIDATE . *"---------------------------------------------------------------------*"*"Local Interface: *" IMPORTING *" VALUE(ID_CANDIDATE) TYPE YPERSON-ID_PERSON *" EXPORTING *" VALUE(ITAB) TYPE YTABLE_TYPE *" RAISING *" YCX_EXCEPTION_T100_TXT *"---------------------------------------------------------------------TRY. SELECT * FROM yperson INTO TABLE itab WHERE id_person = id_candidate. IF sy-subrc <> 0. RAISE EXCEPTION TYPE ycx_exception_t100_txt EXPORTING textid = ycx_exception_t100_txt=>ycx_no_candidate id_candidate = id_candidate. ENDIF. ENDTRY. ENDFUNCTION.
Listing 12.1 Shows the implementation of YFM_SEARCH_CANDIDATE
262
12 Web Dynpro Model
Listing 12.2 shows the implementation of the YFM_SELECT_CANDIDATE. Listing 12.2 Implementation of YFM_SELECT_ CANDIDATE
FUNCTION YFM_SELECT_CANDIDATE. *"---------------------------------------------------------------------*"*"Local Interface: *" EXPORTING *" VALUE(ITAB) TYPE YTABLE_TYPE *" RAISING *" YCX_EXCEPTION_T100_TXT *"---------------------------------------------------------------------TRY. SELECT * FROM yperson INTO TABLE itab. IF sy-subrc <> 0. RAISE EXCEPTION TYPE ycx_exception_t100_txt EXPORTING textid = ycx_exception_t100_txt=>ycx_select_no_posible. ENDIF. ENDTRY. ENDFUNCTION.
This FM selects the information about all the candidates. In this case, we create a new message ID – 001 “Data cannot be selected!” and a new exception ID YCX_ SELECT_NO_POSSIBLE with the text from the message class – message ID 001. Listing 12.3 shows the implementation of YFM_INSERT_CANDIDATE. FUNCTION YFM_INSERT_CANDIDATE . *"---------------------------------------------------------------------*"*"Local Interface: *" IMPORTING *" VALUE(ID_CANDIDATE) TYPE YPERSON-ID_PERSON *" VALUE(FIRSTNAME) TYPE YPERSON-FIRSTNAME *" VALUE(LASTNAME) TYPE YPERSON-LASTNAME *" VALUE(AGE) TYPE YPERSON-AGE *" VALUE(TELEPHONE) TYPE YPERSON-TELEPHONE *" VALUE(ID_COUNTRY) TYPE YPERSON-ID_COUNTRY *" RAISING *" YCX_EXCEPTION_T100_TXT *"---------------------------------------------------------------------DATA wa_person TYPE yperson. wa_person-mandt = sy-mandt. wa_person-id_person = id_candidate. wa_person-firstname = firstname. wa_person-lastname = lastname. wa_person-age = age. wa_person-telephone = telephone. wa_person-id_country = id_country. TRY. INSERT into yperson values wa_person. IF sy-subrc <> 0. RAISE EXCEPTION TYPE ycx_exception_t100_txt EXPORTING textid = ycx_exception_t100_txt=>ycx_insert_no_possible. ENDIF. ENDTRY. ENDFUNCTION.
Listing 12.3 Implementation of YFM_INSERT_CANDIDATE
12.1 Assistance Class as a Model for a Multicomponent Application
263
This FM inserts in the database table YPERSON the information about a candidate. In this case, we create a new message ID – 002 “Candidate insert cannot be done!” and a new exception ID YCX_INSERT_NO_POSSIBLE with the text from the message class – message ID 002. . In this way, we can A FM can be tested by using the Test/Execute Button check if our created FM works correctly. Then, we implement our first method from the assistance class. Figure 12.3 shows the implementation of the SEARCH_CANDIDATE method.
Fig. 12.3 Implementation of the SEARCH_CANDIDATE method
To call a FM, we can use the Pattern Button
Fig. 12.4 Pattern
(Fig. 12.4).
264
12 Web Dynpro Model
Figure 12.5 shows the implementation of the second method from our assistance class.
Fig. 12.5 Implementation of the SELECT_CANDIDATE method
Figure 12.6 shows the implementation of the last method of our assistance class.
Fig. 12.6 Implementation of the INSERT_CANDIDATE method
The Class Builder provides a test environment for classes. We can test our class by using the same test/execute Button (Fig. 12.7).
12.1 Assistance Class as a Model for a Multicomponent Application
265
Fig. 12.7 Testing the assistance class
In this way, we have autonomous units that can be independently tested before we integrate them into bigger applications. If we look backwards to the example that refers to the Exception class with OTR text, we can see that the entire coding was integrated in a method of the view controller. So, we didn’t separate the application layer from the business layer and from the presentation layer. We create the presentation layer through a WD application. We create a main component named Y_MAIN, in which we will use three secondary elements: Y_SEARCH, Y_SELECT and Y_INSERT (Fig. 12.8).
Fig. 12.8 WD component’s structure
266
12 Web Dynpro Model
All the components defined the same assistance class, the YCL_AC_MODEL. Any changes made to the model class in the Framework are available for any other component that has this model class defined as assistance class. In this way, we can share data among components. As we have mentioned above, each ABAP class can be used as a model class, but the services offered by the Web Dynpro Framework in this respect are available only for an assistance class that inherits the abstract class CL_WD_COMPONENT_ ASSISTANCE. The Y_MAIN component represented the start point of this application; it is the only component that has a Web Dynpro application defined. We assign our assistance class YCL_AC_MODEL for our components (Fig. 12.9).
Fig. 12.9 Assistance class assigned to our components
The View Layout for the main component is presented in Fig. 12.10.
Fig. 12.10 The V_MAIN layout
12.1 Assistance Class as a Model for a Multicomponent Application
267
By using the ViewContainerUIElement, we show one of the views: V_SELECT, V_INSERT or V_SEARCH. To be able to navigate among the three used Views, we have to define three outbound plugs. Figure 12.11 shows the defined outbound plugs and the window structure.
Fig. 12.11 Outbound plugs
Before being able to create the instance of the used components, we have to create usages at the V_MAIN View level. When the user presses the linkToAction UI element – Insert – the Framework triggers the event handler method onactioninsert (Listing 12.4). METHOD onactioninsert . DATA: lr_cmp_usage TYPE REF TO if_wd_component_usage. lr_cmp_usage = wd_this->wd_cpuse_insert( ). IF lr_cmp_usage->has_active_component( ) IS INITIAL. lr_cmp_usage->create_component( assistance_class = me->wd_assist ). ENDIF. Wd_this->fire_op_to_v_insert_plg( ). ENDMETHOD.
Listing 12.4 Event handler method
As we can see, through the statement lr_cmp_usage > create_component (assistance_class = me>wd_assist), the existing instance for the assistance class that belongs to the main component is assigned to the used component instance. In this way, we ensure that both components access the same instance of the assistance class. The event handler methods onactionselect and onactionsearch have the same structure, excepting the outbound plug NAME that is fired when the user presses the respective linkToAction UI elements (Listing 12.5).
268 Listing 12.5 Event handler methods
12 Web Dynpro Model METHOD onactionsearch . ….……. wd_this->fire_op_to_v_search_plg( ). ENDMETHOD. METHOD onactionselect. …………… wd_this->fire_op_to_v_select_plg( ). ENDMETHOD.
In this way, we create the instance of the used component and we specify the reference to the active instance of the assistance class. The V_SELECT view layout and the context structure are presented in Fig. 12.12.
Fig. 12.12 View layout and context
Here, we show all the records from our YPERSON database table. The node “CANDIDATE” has the dictionary structure YPERSON, cardinality 1...n, Singleton, supply function SUPPLY_CANDIDATE (Listing 12.6).
Listing 12.6 Supply function method
METHOD supply_candidate. wd_this->populate_node( ). ENDMETHOD.
As we can see, we call the user defined method POPULATE_NODE to populate the context node with values. We have chosen to create this method in order to populate with data the context node and to update its contained data every time the user presses the Refresh button. Listing 12.7 shows the user defined method POPULATE_NODE. When the component Y_SELECT is called, the assistance class is automatically instantiated. Then, this instance is available through the attribute WD_ASSIST: lt_person = wd_assist!select_candidate( ).
12.1 Assistance Class as a Model for a Multicomponent Application
269
METHOD populate_node. DATA lr_node TYPE REF TO if_wd_context_node. DATA ls_data TYPE wd_this->element_candidate. DATA lr_oref TYPE REF TO ycx_exception_t100_txt. DATA lt_person TYPE STANDARD TABLE OF yperson. lr_node = wd_context->get_child_node( 'CANDIDATE' ). TRY. lt_person = wd_assist->select_candidate( ). lr_node->bind_table( new_items = lt_person ). CATCH ycx_exception_t100_txt INTO lr_oref. DATA lr_api_controller TYPE REF TO if_wd_controller. DATA lr_message_manager TYPE REF TO if_wd_message_manager. lr_api_controller ?= wd_this->wd_get_api( ). lr_message_manager = lr_api_controller->get_message_manager( ). lr_message_manager->report_exception( message_object =lr_oref). ENDTRY. ENDMETHOD.
Listing 12.7 The POPULATE_NODE method
In this way, we call the method select_candidate from the assistance class and we pass the result in the lt_person internal table. When the user presses the Refresh button, the Framework triggers the event handler method onactionrefresh (Listing 12.8). Listing 12.8 The ONACTIONREFRESH event handler method
METHOD onactionrefresh. wd_this->populate_node( ). ENDMETHOD.
The V_INSERT view layout and the context structure are presented in Fig. 12.13.
Fig. 12.13 View layout and the view context
The CANDIDATE node has the dictionary structure YPERSON, cardinality 1...1, Singleton. By using this component, we insert records in our database table YPERSON.
270
12 Web Dynpro Model
When the user presses the Save Button, the Framework triggers the event handler method onactionsave (Listing 12.9). METHOD onactionsave. DATA lr_oref TYPE REF TO ycx_exception_t100_txt. DATA lr_node TYPE REF TO if_wd_context_node. DATA lr_element TYPE REF TO if_wd_context_element. DATA ls_data TYPE wd_this->element_candidate. DATA: lv_firstname LIKE ls_data-firstname, lv_lastname LIKE ls_data-lastname, lv_age LIKE ls_data-age, lv_telephone LIKE ls_data-telephone, lv_id_country LIKE ls_data-id_country. lr_node = wd_context->get_child_node( 'CANDIDATE' ). lr_element = lr_node->get_element( ). lr_element->get_static_attributes( IMPORTING static_attributes = ls_data ). lv_firstname = ls_data-firstname. lv_lastname = ls_data-lastname. lv_age = ls_data-age. lv_telephone = ls_data-telephone. lv_id_country = ls_data-id_country. TRY. wd_assist->insert_candidate( firstname = lv_firstname lastname = lv_lastname age = lv_age telephone = lv_telephone id_country = lv_id_country ). DATA: lv_success_text TYPE string. lv_success_text = wd_assist->if_wd_component_assistance~get_text('M01' ). wd_this->atr_mm->report_success( message_text = lv_success_text). CATCH ycx_exception_t100_txt INTO lr_oref. wd_this->atr_mm->report_exception( message_object = lr_oref ) . ENDTRY. ENDMETHOD.
Listing 12.9 The onactionsave event handler method
We have to firstly verify if the end user has inserted values in all the mandatory fields. To perform this check, we use the wdDoBeforeReaction Hook method that has the structure presented in the “view controller methods” chapter. If the user has inserted values in all the fields, we call the method insert_candidate from the model class and we pass the inserted values in the method parameters. wd_assist!insert_candidate( firstname = lv_firstname lastname = lv_lastname age = lv_age telephone = lv_telephone id_country = lv_id_country ). In case the data were successfully saved, we inform the end user about this, through a message defined in our assistance class with the identification symbol M01.
12.1 Assistance Class as a Model for a Multicomponent Application
271
When an exception occurs, we show to the end user this message through the report_exception method. “Atr_mm” represents an attribute created in the attribute tag of the current view. This is declared of ref to if_wd_message_manager type. By using the wdDoInit Hook method, we pass in the atr_mm attribute the reference to the Message Manager: DATA lr_api_controller TYPE REF TO if_wd_controller.lr_api_controller ?= wd_this!wd_get_api( ).wd_this!atr_mm = lr_api_controller!get_message_ manager( ). The V_SEARCH view layout and the context structure are presented in Fig. 12.14.
Fig. 12.14 View layout and context structure
The context structure is the same as for the context realized to exemplify the exception class with OTR text. When the user presses the Search Button, the Framework triggers the onactionsearch event handler method (Listing 12.10). METHOD onactionsearch. DATA lr_oref TYPE REF TO ycx_exception_t100_txt. DATA: lt_candidate TYPE STANDARD TABLE OF yperson, lr_node TYPE REF TO if_wd_context_node, lv_id_candidate TYPE yperson-id_person. lr_node = wd_context->get_child_node( 'SEARCH' ). lr_node->get_attribute( EXPORTING name =' ID_PERSON' IMPORTING value = lv_id_candidate ). TRY. lt_candidate = wd_assist->search_candidate( id_candidate = lv_id_candidate ). DATA lr_subnode TYPE REF TO if_wd_context_node. lr_subnode = lr_node->get_child_node( 'PERSON' ). lr_subnode->bind_table( new_items = lt_candidate ). CATCH ycx_exception_t100_txt INTO lr_oref. wd_this->atr_mm->report_exception( message_object = lr_oref ). ENDTRY. ENDMETHOD.
Listing 12.10 Event handler method
272
12 Web Dynpro Model
When the component Y_SEARCH is called, the assistance class is automatically instantiated. Then, this instance is available through the attribute WD_ASSIST: lt_candidate = wd_assist!search_candidate( id_candidate = lv_id_candidate ). In this way, we call the method search_candidate from the assistance class and we pass the result in the lt_candidate internal table. When an exception occurs, we show the message to the end user, through the report_exception method. Figure 12.15 shows the runtime result.
Fig. 12.15 Runtime
12.1 Assistance Class as a Model for a Multicomponent Application
273
We can extend our application by adding the possibility to change a candidate record. For the database table YPERSON, we have defined in the ABAP Dictionary a Lock Object. We can use it to synchronize the access to the same data in our database table YPERSON with more that one WD application (Fig. 12.16).
WD Application Browser 2
WD Application Browser 1
Modify records
Modify records
Write entries are locked Request collides
YPERSON
Fig. 12.16 Locking objects
To set a lock and to release a lock, we can define, in our assistance class, two additional methods that use the generated Function Modules ENQUEUE_YPERSON and DEQUEUE_YPERSON. After this, we call our defined methods from our WD methods every time we want to lock one or more data records or to release the locked data records. Tip For more details about ABAP lock and LUW concepts, please refer to the book ABAP Objects (Keller & Kruger)
In case we need to perform a search in a database table to find all the records that contain a certain searched pattern, we can use the ABAP classes CL_ABAP_ REGEX and CL_ABAP_MATCHER. In our case, we search the database table YPERSON, column “firstname”, to find all the records that contain the string we are looking for. This value will be found in the local variable lv_firstname (Listing 12.11).
274
12 Web Dynpro Model TYPES: BEGIN OF st_person, mandt TYPE yperson-mandt, id_person TYPE yperson-id_person, firstname TYPE yperson-firstname, lastname TYPE yperson-lastname, telephone TYPE yperson-telephone, age TYPE yperson-age, id_country TYPE yperson-id_country, END OF st_person. DATA: it_person TYPE TABLE OF st_person, lv_firstname TYPE yperson-firstname. FIELD-SYMBOLS LIKE LINE OF it_person. SELECT * FROM yperson INTO TABLE it_person. LOOP AT it_person ASSIGNING . IF cl_abap_matcher=>contains( pattern = lv_firstname text = -firstname ) = abap_true. INSERT INTO TABLE itab. ENDIF. ENDLOOP.
Listing 12.11 Search with CL_ABAP_MATCHER
As can be seen, we used the static method CONTAINS of the class CL_ABAP_ MATCHER, where “pattern” represents the searched pattern and “text” represents the text we search to find this pattern. The result will be “abap_true” if the search was successfully finalized: cl_abap_matcher=>contains(pattern = lv_firstnametext = ! firstname ) = abap_true. After each successful search, we insert the respective records in the internal table itab. Then, we populate with these values the node bound at the table where the results are displayed.
12.2
BAPI as a Model
BAPI are standard SAP interfaces, defined as methods for the business object types that can be used in the business data exchange among the SAP components, and among the SAP and the non SAP components. In our example, we use the YFM_SEARCH_CANDIDATE Function Module to create a simple BAPI example that we use as a model in a WD component. To be able to do this, we should firstly make some changes at the Function Module level.
12.2.1
Creating a BAPI
We create a new Function Group, where we copy the YFM_SEARCH_CANDIDATE and rename it YBAPI_YCANDIDATE_SEARCH. For a BAPI, we have a
12.2 BAPI as a Model
275
name convention BAPI__<method_name>. In case of a search( ) BAPI, which reads the details for the object type YCANDIDATE, the name of the associated Function Module is YBAPI_YCANDIDATE_SEARCH. In the Attributes tab of the Function Module, we have to activate the option Remote-Enabled Module (Fig. 12.17). Fig. 12.17 The remoteenabled module option – RFC
After this, we create a structure in the ABAP Dictionary with the same components as our YPERSON table (Fig. 12.18).
Fig. 12.18 Structure YBAPI_YPERSON
We use this structure to define our parameters id_candidate type YBAPI_ YPERSON-ID_PERSON and itab LIKE YBAPI_YPERSON. Now, we have to make another change, because we cannot use exceptions anymore.
276
12 Web Dynpro Model
RAISE EXCEPTION TYPE ycx_exception_t100_txt EXPORTING textid = ycx_exception_t100_txt=>ycx_no_candidate id_candidate = id_candidate. In order to return a message in case no records exist in the database table YPERSON with the specified ID, we use an export Return parameter for returning the exception messages to the calling application. With this Return parameter, based on the reference structure BAPIRET2, we are able to record and classify all the possible errors that may occur. The structure BAPIRET2 has the structure presented in Fig. 12.19.
Fig. 12.19 The BAPIRET2 structure
We can fill this structure via the Function Module BALW_BAPIRETURN_ GET2 (Listing 12.12).
Listing 12.12 Pattern for BALV_BAPIRETURN_ GET2
CALL FUNCTION 'BALW_BAPIRETURN_GET2' EXPORTING type = cl = number = * PAR1 ='' * PAR2 ='' * PAR3 ='' * PAR4 ='' * LOG_NO ='' * LOG_MSG_NO ='' * PARAMETER ='' * ROW =0 * FIELD ='' * IMPORTING * RETURN = .
12.2 BAPI as a Model
277
The Listing 12.13 shows the Function Module structure. FUNCTION ybapi_ycandidate_search . *"---------------------------------------------------------------------*"*"Global Interface: *" IMPORTING *" VALUE(ID_CANDIDATE) TYPE YBAPI_YPERSON-ID_PERSON *" TABLES *" ITAB STRUCTURE YBAPI_YPERSON OPTIONAL *" RETURN STRUCTURE BAPIRET2 OPTIONAL *"---------------------------------------------------------------------DATA msg_id_candidate LIKE sy-msgv1. CLEAR msg_id_candidate. REFRESH: return, itab. SELECT * FROM yperson INTO TABLE itab WHERE id_person = id_candidate. IF sy-subrc <> 0. msg_id_candidate = id_candidate. CALL FUNCTION 'BALW_BAPIRETURN_GET2' EXPORTING type = 'E' cl = 'YCL_T100_MSG' number = '000' par1 = msg_id_candidate IMPORTING return = return. APPEND return. ELSE. APPEND return. ENDIF. ENDFUNCTION.
Listing 12.13 Function module
As we can see, instead of raising an exception in case we don’t find any records with the specified ID, we use the BALW_BAPIRETURN_GET2 Function Module to fill the structure BAPIRET2. We have used the defined YCL_T00_MSG message class number 000, and we have replaced the parameter placeholder with the value inserted by the user as a candidate ID. After saving and activating, we can release our Function Module: Function Module ! Release ! Release. As result of our RELEASE action, we’ll get a message of YBAPI_YCANDIDATE_SEARCH type. By using the SWO1 (Business Object Builder) transaction, we create an object named YCANDIDATE (Fig. 12.20).
278
12 Web Dynpro Model
Fig. 12.20 Creating the object candidate
We add a Method named SEARCH: Utilities ! API Methods ! Add Method (Fig. 12.21).
Fig. 12.21 Creating the API method
We have to release our object. We choose from the menu Edit ! Change Release Status ! Object Type ! To model. We make the same steps for To implement and To release, and the same steps for Object Type Component.
12.2 BAPI as a Model
279
After releasing the object, we can test it (Fig. 12.22).
Fig. 12.22 Testing the BAPI
12.2.2
Using the Created BAPI as a Model
We create a WD component named Y_BAPI, where we use the created BAPI as a model to obtain the data required from the database table YPERSON (Fig. 12.23).
Fig. 12.23 WD component structure
By right-clicking on the WD component name, we choose from the contextual menu Create ! Service call. The Web Dynpro Wizard is open, creating an appropriate context structure and generating a method that contains the required coding for the service call. The Wizard steps are: l l
Start Select controller – we use the existing controller (Fig. 12.24)
Fig. 12.24 Selecting the controller
280 l
12 Web Dynpro Model
Select Service Type – we select the Function Module (Fig. 12.25)
Fig. 12.25 Selecting the service type
l
Select Service – we specify only the name of the YBAPI_YCANDIDATE_ SEARCH Function Module; the Destination box remains unfilled (blank) (Fig. 12.26). In this way, the Function Module will be locally called
Fig. 12.26 Selecting the service
l
Adapt Context – here, we can choose which object type we want to use to represent the service function parameters in the WD controller: as a parameter, as a controller attribute or as a context node or context attribute (Fig. 12.27)
Fig. 12.27 Adapting the context
12.2 BAPI as a Model l
281
Specify Method Name – we have to specify the name of the generated method that shall execute the service (Fig. 12.28)
Fig. 12.28 Specifying the method name
l
Generate Controller
After the last step, we press the COMPLETED button and the wizard ends. It generates the COMPONENTCONTROLLER context and the proper method EXECUTE_YBAPI_YCANDIDATE_SEARC that shall execute the service (Fig. 12.29).
Fig. 12.29 The generated context and method
The node IMPORTING contains the ID_CANDIDATE attribute in which is stored the value of the ID we are looking for. The node CHANGING contains the two nodes ITAB and RETURN. The node ITAB holds the information about the candidate with the searched ID. The node RETURN has the structure BAPIRET2; we need to use its message attribute to display the return messages on the screen for the end user. The View layout has the structure presented in Fig. 12.30.
282
12 Web Dynpro Model
Fig. 12.30 View layout and view context
When the user presses the button to look for a candidate, the Framework triggers the event handler method onactionsearch (Listing 12.14). METHOD onactionsearch. wd_comp_controller->execute_ybapi_ycandidate_searc( ). DATA: lr_bapi_node TYPE REF TO if_wd_context_node, lr_changing TYPE REF TO if_wd_context_node, lr_return TYPE REF TO if_wd_context_node. DATA lv_bapi_message TYPE bapi_msg. lr_bapi_node = wd_context->get_child_node( `YBAPI_YCANDIDATE_SEA` ). lr_changing = lr_bapi_node->get_child_node( `CHANGING` ). lr_return = lr_changing->get_child_node( `RETURN` ). lr_return->get_attribute( EXPORTING name = 'MESSAGE' IMPORTING value = lv_bapi_message ). IF lv_bapi_message IS NOT INITIAL. DATA:lr_api_controller TYPE REF TO if_wd_controller, lr_message_manager TYPE REF TO if_wd_message_manager. lr_api_controller ?= wd_this->wd_get_api( ). lr_message_manager = lr_api_controller->get_message_manager( ). lr_message_manager->report_error_message( message_text = lv_bapi_message ). ENDIF. ENDMETHOD.
Listing 12.14 Event handler method
The mode of calling the BAPI is encapsulated in the method generated by the wizard in COMPONENTCONTROLLER. All we have to do is to call this method: wd_comp_controller!execute_ybapi_ycandidate_searc( ).
12.3 Web Service
283
When the searched ID doesn’t exist in the database table YPERSON, we show the proper error message stored in the attribute message of the RETURN node. Figure 12.31 shows the runtime result.
Fig. 12.31 Runtime
12.3
Web Service
The Application Server ABAP can be a Web Service provider and a Web Service required. Figure 12.32 shows the basic architecture of the Web Service Framework of AS ABAP.
WSDL
Discover
2
UDDI Service Directory
1
Publish
WS PROVIDER
WS CLIENT 3
Bind
Fig. 12.32 Basic web service framework architecture
284
12 Web Dynpro Model
The Web Service provider creates the WS and its definition. After this, it can publish the WSDL document to a Universal Description Discovery and Integration (UDDI) service directory, or it can create a direct exchange of WSDL document with the WS client. The Web Service Description Language (WSDL) is a special form of XML that contains all the information required by a client to connect with the Web Service provider and all the required information to programmatically work with the respective service (e.g. number of parameters passed to the service, structure of the returned result, type of the used parameters). We can store the released Web Services in an UDDI registry. There are many organizations that offer web services we can use for free. Such free Web Services we can find at URL http://www.xmethods.net/ve2/index.po. The web address of the public UDDI service directory for SAP we can find at URL http://uddi.sap.com. With the ABAP Workbench, we have many options to create a Web Service (inside-out type). We can use, for example, a BAPI, a Function Module, a Function Group or an Interface message. In our case, we want to provide the same search option for our YPERSON database table. A Function Module implementation will be used as a Web Service endpoint. After Function Module implementation, we create the Web Service definition with only a few mouse clicks, we test it and we consume it in the Web Dynpro ABAP, as a model for our WD component. In our case, we don’t focus on the WS security, but we only create a small example required to exemplify how we can consume a Web Service in the Web Dynpro ABAP. Tip For more detailed information about the Web Services, please refer to the Book SAP NetWeaver Security by Martin Raepple.
12.3.1
Creating the Web Service
First, we copy the Function Module used to search for a candidate and we slightly modify it (Listing 12.15). To be possible to further transform it into a RFC-enabled Module, in the Attributes tab of the Function Module, we have to activate the option Remote-Enabled Module. As we have mentioned before, no exception classes can be used in the RFCenabled Function Module. This is the reason why, for the purpose of this example, we have chosen to create a non class exception: NO_ID. To manage the exceptions that may occur, we can use the BAPIRET2 structure similar to the latter example.
12.3 Web Service Listing 12.15 Implementation of YFM_SEARCH_PERSON
285 FUNCTION YFM_SEARCH_PERSON. *"--------------------------------------------------------------------*"*"Local Interface: *" IMPORTING *" VALUE(ID_CANDIDATE) TYPE YPERSON-ID_PERSON *" EXPORTING *" VALUE(FIRSTNAME) TYPE YPERSON-FIRSTNAME *" VALUE(LASTNAME) TYPE YPERSON-LASTNAME *" VALUE(TELEPHONE) TYPE YPERSON-TELEPHONE *" VALUE(AGE) TYPE YPERSON-AGE *" VALUE(ID_COUNTRY) TYPE YPERSON-ID_COUNTRY *" EXCEPTIONS *" NO_ID *"---------------------------------------------------------------------DATA wa_person TYPE yperson. SELECT SINGLE firstname lastname telephone age id_country INTO CORRESPONDING FIELDS OF wa_person FROM yperson WHERE id_person EQ id_candidate. if sy-subrc <> 0. raise no_id. endif. firstname = wa_person-firstname. lastname = wa_person-lastname. telephone = wa_person-telephone. age = wa_person-age. id_country = wa_person-id_country. ENDFUNCTION.
Then, we transform our RFC into a Web Service. We have many possibilities to do this, as follows: l
l
Right click on the FM name and, from the contextual menu, we choose Create ! Web Service. From Function Builder (Transaction SE37), we choose from the menu Utilities ! More Utilities ! Create Web Services.
The Wizard steps are: Object Type – we can choose the object type; in our case, the Web Service is a service provider (Fig. 12.33).
Fig. 12.33 Object type wizard step
Service Provider – we create a service provider for an existing ABAP Object (Inside Out) (Fig. 12.34).
286
12 Web Dynpro Model
Fig. 12.34 Service provider wizard step
Object type – here, we enter a name and a short description for our Web Service, and we can choose the type of the Endpoint use (Fig. 12.35).
Fig. 12.35 Object type wizard step
Choose Endpoint – here, we can enter the name of the Function Module that we want to use as endpoint for our Web Service (Fig. 12.36).
Fig. 12.36 Choosing the endpoint wizard step
Configure Service – here, we choose an Authorization profile. As we have mentioned above, for the purpose of this example we choose the profile PRF_DT_IF_SEC_NO (Fig. 12.37).
Fig. 12.37 Configuring the service wizard step
Enter Package/Request – here, we have to enter the name of the package Y_WEBDYNPRO and the Transport Request. Complete – it’s the last step in the wizard, where we are informed that the Web Service with the desired name will be generated after pressing the “Complete” button.
12.3 Web Service
287
As result, we can see the Service Definition (Fig. 12.38).
Fig. 12.38 The generated service definition
12.3.2
Web Service Configuration
To perform the necessary configuration tasks, we use the SOA Manager, accessible through the SOAMANAGER transaction. By using “Single Service Administration”, we can search for our created WS and configure it (Fig. 12.39). We can find this option in the tab: “Application and Scenario Communication”.
Fig. 12.39 Searching for our web service
By pressing the “Apply Selection” button, we can see the Details of our Service Definition. Using the “Configurations” tab, we can create a Service and a ServiceEndpoint for our Service Definition YWEB_SERVICE (Fig. 12.40).
288
12 Web Dynpro Model
Fig. 12.40 Details of service definition – configurations
Each Service Definition may have more than one Service and, for each Service, we can create more than one Endpoint. Each Service-Endpoint can configure a service in a different way.
12.3.3
Testing the Web Service
After configuring our endpoint, we save it and go into the “Overview” tab (Fig. 12.41).
Fig. 12.41 Details of service definition – overview
From here, we choose the link “Open WSDL document for selected binding” and we copy the URL address from the window that appears. By selecting the link “Open Web Service navigator for selected binding”, the Web Service test page opens and we can test our new created Web Service after pressing the “Test” button (Fig. 12.42).
12.3 Web Service
289
Fig. 12.42 Web service navigator
In case an error occurs, we have to configure the J2EE server access information (the host name and a port number), because the Web Service test page (Web Service Navigator) runs on Java stack. To do this, we can use the same SOAMANAGER transaction ! the tab Technical Configuration ! the option System Global Settings. We can test our Web Service (Fig. 12.43).
Fig. 12.43 Testing our web service – request/response
12.3.4
Consuming the Web Service in Web Dynpro
To be able to consume the created Web Service into the Web Dynpro application, we have to firstly create a Proxy. To create it, we can use the same Wizard as for the Web Service creation. In this case, the Wizard steps are: Object type – Service Consumer (Fig. 12.44).
290
12 Web Dynpro Model
Fig. 12.44 Wizard – object type step
Select Source – offers the possibility to select the source of the WSDL document (Fig. 12.45).
Fig. 12.45 Wizard – selected source step
Select Source – here, we enter our Web Service’s URL (Fig. 12.46). We can use copy and paste to take this URL from the SOAMANAGER transaction.
Fig. 12.46 Wizard – selected source step
Enter Package/Request – we have to enter the package name, the prefix and the Workbench Request (Fig. 12.47). Because, in the same time with the generation of the proxy class, there are also generated other development objects (e.g. Dictionary objects, classes and interfaces), it is recommended to generate these objects in a separate package (in our case, the Y_PROXY package).
12.3 Web Service
291
Fig. 12.47 Wizard – enter package/request step
Complete – after the last step, the Wizard generates the consumer proxy (Fig. 12.48).
Fig. 12.48 The consumer proxy
The generated development objects are presented in Fig. 12.49.
Fig. 12.49 Generated development objects
292
12 Web Dynpro Model
Before pressing the RUN button to test our Consumer Proxy, we have to create a logical port by using the SOAMANAGER transaction or the old LPCONFIG transaction. In the SOAMANAGER transaction, in the same window where we searched for the Web Service, we can search now for a consumer proxy with the external name: “yweb_service” (Fig. 12.50).
Fig. 12.50 Searching for a consumer proxy
By pressing the “Apply Selection” button, we open the field where we can create the Proxy Definition. Into the “Configurations” tab, we can create the Logical Port. In the next step, we have to create the Web Dynpro component to use the created Client Proxy. We create a Web Dynpro component named Y_WS_CONSUMER with a view named V_VIEW and a default window. By using the Service Call (similar to the “BAPI” example), we can integrate our Client Proxy into our WD application. In this case, we have to use the “Web Service Proxy” option as service type. Then, we have to enter the proxy class name, the public method and the logical port. Because in the latter example we showed how to use this Wizard, now we are going to show, through this example, how to use the proxy without the Wizard’s help. In case we have more complex structures, it happens that Wizard generates only one attribute instead of a node with attributes. In this case, we have to make manually the adequate modifications. The V_VIEW view context and the layout are presented in Fig. 12.51. The ID_PERSON attribute is of the YPERSON-ID_PERSON type and shall be used to maintain the ID of the searched competitor. The Person child node has the YPERSON dictionary structure, so here we are going to find the data about the searched competitor: his first name, last name, telephone, age and his country id. In the View Layout, we have inserted the UI elements: Group, InputField, Label and Table.
12.3 Web Service
293
Fig. 12.51 View context und view layout
When the user presses the Search button, the Framework triggers the event handler method onactionsearch (Listing 12.16).
Listing 12.16 The onactionsearch event handler method
METHOD onactionsearch . DATA: lr_node TYPE REF TO if_wd_context_node, lr_subnode TYPE REF TO if_wd_context_node, ls_subnode TYPE wd_this->element_person, lv_id_person TYPE yperson-id_person. DATA: obj1 TYPE REF TO ysco_yweb_service, obj2 TYPE REF TO cx_ai_system_fault, ls_input TYPE ysyfm_search_person, ls_output TYPE ysyfm_search_personresponse. lr_node = wd_context->get_child_node( 'SEARCH_PERSON' ). lr_subnode = lr_node->get_child_node('PERSON' ). lr_node->get_attribute( EXPORTING name = 'ID_PERSON' IMPORTING value = lv_id_person ). TRY. CREATE OBJECT obj1. CATCH cx_ai_system_fault INTO obj2. ENDTRY. ls_input-id_candidate = lv_id_person. TRY. CALL METHOD obj1->yfm_search_person EXPORTING input = ls_input IMPORTING output = ls_output. CATCH cx_ai_system_fault INTO obj2. CATCH cx_ai_application_fault . ENDTRY. IF ls_output IS INITIAL. DATA lr_api_controller TYPE REF TO if_wd_controller. DATA lr_message_manager TYPE REF TO if_wd_message_manager. lr_api_controller ?= wd_this->wd_get_api( ). lr_message_manager = lr_api_controller->get_message_manager( ). lr_message_manager->report_exception( message_object = obj2 ). ELSE. ls_subnode-firstname = ls_output-firstname. ls_subnode-lastname = ls_output-lastname. ls_subnode-telephone = ls_output-telephone. ls_subnode-age = ls_output-age. ls_subnode-id_country = ls_output-id_country. lr_subnode->set_static_attributes( ls_subnode ). ENDIF. ENDMETHOD.
294
12 Web Dynpro Model
When we use proxy objects in methods or programs we can use drag and drop to ease the code generation (Fig. 12.52).
Drag & drop
Fig. 12.52 Drag and drop for code generation
As we can see, we have declared a reference variable for proxy (obj1 TYPE REF TO ysco_yweb_service) and two local structures to set the input parameter (ls_input TYPE ysyfm_search_person) and to get the response (ls_output TYPE ysyfm_ search_personresponse). After creating the proxy, we call it and pass the response values in the corresponding child node “PERSON”. At runtime, we have (Fig. 12.53):
Fig. 12.53 Runtime
Chapter 13
ALV and Select Options
“I never know what I’m going to put on the canvas. The canvas paints itself. I’m just the middleman.” Peter Max
Abstract The following section details and describes the modality to use the standard components ALV and SO as assistance, in creating our own Web Dynpro applications. We start from a simple example, where ALV is used to display the data in a table, and we end by using both components for advanced search and display the searched data, disposing of the extra functionalities offered by ALV (e.g. exporting data in Excel). SAP List Viewer (ALV) is a tool we c.an use to display data in a two-dimensional table, in a hierarchical-sequential list or in a tree structure. It allows us to use it in a large range of applications, from the classical Dynpros to the Web Dynpro. In our examples, we use in Web Dynpro the ALV component SALV_WD_TABLE to display data in a two-dimensional table. Through “Select Options”, we can benefit of complex searching possibilities. For example, we use the WDR_SELECT_OPTIONS component to create a selection option screen that offers, in the same time, four standard buttons: Cancel, Reset, Done and Check.
13.1
SAP List Viewer
In this subchapter, through some examples, we will meet the SALV_WD_TABLE standard component and its advantages.
U. Gellert and A.D. Cristea, Web Dynpro ABAP for Practitioners, DOI 10.1007/978-3-642-11385-7_13, # Springer-Verlag Berlin Heidelberg 2010
295
296
13.1.1
13 ALV and Select Options
Simple ALV Example
We create a WD component that displays all the information about candidates by using the SALV_WD_TABLE, ALV component. To be able to use this component, we have to firstly define a usage. Figure 13.1 shows the WD component structure and the usage definition.
Fig 13.1 WD component structure
In the COMPONENTCONTROLLER, we create a node PERSON with the dictionary structure YPERSON, Singleton, Cardinality 0. . .n and supply function SUPPLY_PERSON (Fig. 13.2).
Fig. 13.2 Context node and supply function
The View Layout has the structure presented in Fig. 13.3.
Fig. 13.3 View layout
In this case, we have chosen to use a ViewContainerUIElement to embed the Table view of the SALV_WD_TABLE component, but we can embed a view or an interface view directly in a Window if we don’t need additional UI elements. The
13.1 SAP List Viewer
297
table view is the central view of an ALV component and represents the container in which the ALV output is displayed. Figure 13.4 shows the Window structure and the selected Interface View.
Fig. 13.4 Window structure and interface views of the ALV component
To be able to create a reverse mapping, we firstly create an interface controller usage (Fig. 13.5).
Fig. 13.5 Interface controller usage
Then, we need to provide the DATA context node with the values from the PERSON context node (Fig. 13.6).
Fig. 13.6 Context mapping
298
13 ALV and Select Options
DATA context node must contain the structure and data of the ALV output. The runtime result is presented in Fig. 13.7.
Fig. 13.7 Runtime result
As we have mentioned above, the ALV component offers new capabilities, as follows: l l l l
Exporting the data displayed into Microsoft Excel, by using the Export button Printing a version in PDF format, by using the Print Version button Simple data filter, by using the Filter option Complex settings, by using the Settings option
The settings option offers the capability to hide some columns, to create complex searches and complex filters, to change the display mode and to create a print version. We can save the changes we made and assign them to the current user as an initial view (Fig. 13.8).
Fig. 13.8 Settings option
13.1 SAP List Viewer
299
After saving the changes, we can see the result (Fig. 13.9).
Fig. 13.9 ALV settings
13.1.2
ALV Configuration Model
To configure an ALV output, we can use: table settings, column settings, field settings, standard function settings or application-specific function settings. By using the transaction SE24, we can see the structure of the CL_SALV_WD_ CONFIG_TABLE (Fig. 13.10). Here, we find the interfaces and their methods to be used to manipulate the ALV output.
Fig. 13.10 CL_SALV_WD_CONFIG_TABLE
300
13.1.2.1
13 ALV and Select Options
Manipulating the ALV Output: Deleting Rows, Hiding Columns, Table Designing, Sorting
We want to manipulate the ALV output to show only five rows, to use the Table Design Alternating to sort table ascending by the id_country field and to hide the first two columns, Client and ID. We use the below example, where we make some changes. We define a usage at the V_VIEW level (Fig. 13.11).
Fig. 13.11 Defining the usage at the View level
We implement the wdDoInit Hook method, Listing 13.1.
METHOD wddoinit . DATA: lr_cmp_usage TYPE REF TO if_wd_component_usage, lr_salv_wd_table TYPE REF TO iwci_salv_wd_table, lr_table TYPE REF TO cl_salv_wd_config_table, lr_field TYPE REF TO cl_salv_wd_field. lr_cmp_usage = wd_this->wd_cpuse_alv_usage( ). IF lr_cmp_usage->has_active_component( ) IS INITIAL. lr_cmp_usage->create_component( ). ENDIF. lr_salv_wd_table = wd_this->wd_cpifc_alv_usage( ). lr_table = lr_salv_wd_table->get_model( ). lr_table->if_salv_wd_column_settings~delete_column( 'MANDT' ). lr_table->if_salv_wd_column_settings~delete_column( 'ID_PERSON'). lr_table->if_salv_wd_table_settings~set_design( cl_wd_table=>e_designalternating ). lr_table->if_salv_wd_table_settings~set_visible_row_count( 5 ). lr_field = lr_table->if_salv_wd_field_settings~get_field( 'ID_COUNTRY' ). lr_field->if_salv_wd_sort~create_sort_rule( ). ENDMETHOD.
Listing 13.1 The wdDoInit Hook method
13.1 SAP List Viewer
301
As we can see, we have used the method GET_MODEL from the interface IWCI_SALV_WD_TABLE. This method has no importing parameters and returns a complete Configuration Model (CL_SALV_WD_CONFIG_TABLE). The ALV component is partly based on the Table UI element. To set the Table design and the number of visible rows, we use the methods set_design and, respectively, set_visible_row_count from the interface IF_SALV_WD_TABLE_ SETTINGS. If we look at the dynamic programming of a Table UI element, we can see that the property for the Table design alternating is cl_wd_table ) e_designalternating, and the property VISIBLE_ROW_COUNT is an integer number (in our case, 5). To delete the two columns, we use the method delete_column from IF_SALV_ WD_COLUMN_SETTINGS interface, and to create a sort rule we use the method create_sort_rule from the IF_SALV_WD_INTERFACE interface. The default sorting rule is: sort_order = if_salv_wd_c_sort)sort_order_asscending Figure 13.12 shows the runtime result.
Fig. 13.12 Runtime
13.1.2.2
Changing the Cell Editor
As we know, the content of a cell to be displayed is specified by the table cell editor of the column. In the default mode, the table cells are created by using the TextView UI element. We change the cell editor for the EU Countries column. In this case, we use a linkToURL UI element that opens the web page where we can find all the information about the EU countries. To do this, we need to add some coding at the below example. We need to dynamically create a linkToURL UI element. The Listing 13.2 shows the additional coding in the wdDoInit Hook method.
302
13 ALV and Select Options DATA: lr_column TYPE REF TO cl_salv_wd_column, lr_link_to_url TYPE REF TO cl_salv_wd_uie_link_to_url. lr_column = lr_table->if_salv_wd_column_settings~get_column( 'ID_COUNTRY' ). CREATE OBJECT lr_link_to_url. lr_link_to_url->set_text_fieldname( 'ID_COUNTRY' ). lr_link_to_url->set_reference( 'http://europa.eu/abc/european_countries/eu_members/index_en.htm' ). lr_column->set_cell_editor( lr_link_to_url ).
Listing 13.2 Changing the cell editor
Figure 13.13 shows the runtime result.
Fig. 13.13 Runtime
13.1.2.3
Adding a Header for the ALV Table
For an ALV table, we can add a header, too. To do this, we have to use the method CREATE_HEADER of the IF_SALV_WD_TABLE_SETTINGS interface (Listing 13.3). DATA: lr_settings_alv_table TYPE REF TO if_salv_wd_table_settings. DATA: lr_alv_header TYPE REF TO cl_salv_wd_header.
lr_settings_alv_table ?= lr_table. lr_alv_header = lr_settings_alv_table->get_header( ). lr_alv_header->set_text( 'ALV Header' ).
Listing 13.3 Header for ALV table
13.1 SAP List Viewer
303
Figure 13.14 shows the runtime.
Fig. 13.14 Header for ALV table
13.1.2.4
Setting the Top of List and the End of List for the ALV Output
For an ALV output, we can create a top of list (header text) and an end of list (footer text). As we have seen, the ALV component we have used provides two context nodes, named TOP_OF_LIST and END_OF_LIST. These context nodes hold the data for header and footer. Each context node contains an attribute named CONTENT of CL_SALV_FORM_ELEMENT type. To be able to access these context nodes from our view V_VIEW, we have to create a context mapping (Fig. 13.15).
Fig. 13.15 Context mapping
304
13 ALV and Select Options
Then, we have to define the basic layout and to create the elements. In our case, we have chosen to use the Row type layout, class CL_SALV_FORM_LAYOUT_ FLOW. We create a text element for the header and a text element for the footer (Listing 13.4). lr_node_top_of_list TYPE REF TO if_wd_context_node. lr_node_end_of_list TYPE REF TO if_wd_context_node. DATA lr_flow_top TYPE REF TO cl_salv_form_layout_flow. DATA lr_flow_end TYPE REF TO cl_salv_form_layout_flow. DATA lr_text_top TYPE REF TO cl_salv_form_text. DATA lr_text_end TYPE REF TO cl_salv_form_text. CREATE OBJECT lr_flow_top. lr_text_top = lr_flow_top->create_text( position = 1 text = 'Header Text' tooltip = 'Top of list' ). CREATE OBJECT lr_flow_end. lr_text_end = lr_flow_end->create_text( position = 1 text = 'Footer Text' tooltip = 'End of list' ). lr_node_top_of_list = wd_context->get_child_node( 'TOP_OF_LIST ' ). lr_node_top_of_list->set_attribute( value = lr_flow_top name = 'CONTENT' ). lr_node_end_of_list = wd_context->get_child_node( 'END_OF_LIST ' ). lr_node_end_of_list->set_attribute( value = lr_flow_end name = 'CONTENT' ). lr_table>if_salv_wd_table_settings~set_top_of_list_visible( value = abap_true ). lr_table>if_salv_wd_table_settings~set_end_of_list_visible( value = abap_true ).
DATA
DATA
Listing 13.4 Header and footer for an ALV table
Figure 13.16 shows the runtime.
Fig. 13.16 Runtime
13.1 SAP List Viewer
13.1.2.5
305
Adding a Self-Defined UI Element to the ALV Toolbar
On the ALV toolbar, we can add our own UI elements. We add a linkToAction UI element (Listing 13.5).
lr_linktoaction TYPE REF TO cl_salv_wd_fe_link_to_action. lr_linktoaction. lr_linktoaction->set_text(' Our self-defined linkToAction ' ). DATA linktoaction TYPE REF TO cl_salv_wd_function. linktoaction = lr_table>if_salv_wd_function_settings~create_function( id = 'LTA' ). linktoaction->set_editor( lr_linktoaction ).
DATA
CREATE OBJECT
Listing 13.5 Adding a linkToAction UI element to the ALV toolbar
Figure 13.17 shows the runtime.
Fig. 13.17 Runtime
To transform our linkToAction into another UI element, we have to change the editor type from the linkToAction (CL_SALV_WD_FE_LINK_TO_ACTION) into another allowed type. For example, to have a button editor, we have to change only the class name: CL_SALV_FE_BUTTON. When the user presses this link, we have to trigger an event handler method. As we can see, we have not defined an action for this link. To know the UI element that was pressed, we use the ON_FUNCTION event. We create an event handler method named LINKTOACTION_ACTION and we choose the event ON_FUNCTION (Fig. 13.18).
306
13 ALV and Select Options
Fig. 13.18 Event handler method for our self-defined linkToAction
If our link with the ID = “LTA” is pressed, a statement block is executed (Fig. 13.19).
Fig. 13.19 Event handler method
13.2
Select Options
We create a WD component that offers complex possibilities to search for a candidate. To be able to use these complex search possibilities, we have used the WDR_SELECT_OPTIONS component. Figure 13.20 shows the WD component structure and the usage definition.
13.2 Select Options
307
Fig. 13.20 The WD component structure
We create, in Context view, the node PERSON with the same structure (Cardinality 0. . .n, dictionary structure YPERSON, Singleton, without supply function). In View Layout, we have to insert a ViewContainerUIElement required to integrate the interface view WND_SELECTION_SCREEN of the Select Option component. Besides this UI element, we need a Button and a Table UI element. Figure 13.21 shows the view context and the view layout.
Fig. 13.21 Context view and view layout
We define a usage at the view level (Fig. 13.22).
Fig. 13.22 How to define the usage
308
13 ALV and Select Options
We create two attributes: M_HANDLER type ref to IF_WD_SELECT_ OPTIONS and M_WD_SELECT_OPTIONS type ref to IWCI_WDR_SELECT_ OPTIONS (Fig. 13.23).
Fig. 13.23 Attributes
We use the wdDoInit Hook method to instantiate the used component WDR_ SELECT_OPTIONS, in order to dynamically create a range table and to add a selection screen Field (Listing 13.6). METHOD DATA:
wddoinit .
rt_range_table TYPE REF TO data, lv_tooltip TYPE string VALUE 'Search for id', lv_abap_bool TYPE boolean VALUE abap_true, lr_componentcontroller TYPE REF TO ig_componentcontroller, lr_cmp_usage TYPE REF TO if_wd_component_usage. lr_cmp_usage = wd_this->wd_cpuse_select_options( ). IF lr_cmp_usage->has_active_component( ) IS INITIAL. lr_cmp_usage->create_component( ). ENDIF. wd_this->m_wd_select_options = wd_this->wd_cpifc_select_options( ). wd_this->m_handler = wd_this->m_wd_select_options->init_selection_screen( ). rt_range_table = wd_this->m_handler->create_range_table( i_typename = 'YIDI' ). wd_this->m_handler->add_selection_field( i_id = 'ID_PERSON' i_obligatory = lv_abap_bool it_result = rt_range_table i_tooltip = lv_tooltip i_value_help_type = if_wd_value_help_handler=>co_prefix_searchhelp i_value_help_id = 'YSH_ID_PERSON' ). ENDMETHOD.
Listing 13.6 The wdDoInit Hook method
By using the method INIT_SELECTION_SCREEN of the IWCI_WDR_ SELECT_OPTIONS interface, we initialize the selection screen. After this, we
13.2 Select Options
309
use the method CREATE_RANGE_TABLE of the IF_WD_SELECT_OPTIONS interface to dynamically create a Range Table. This method has three importing parameters: I_TYPENAME type STRING, I_LENGTH type I, I_DECIMALS type I and a returning parameter RT_RANGE_TABLE type ref to data. The I_TYPENAME is not optional; we use it to specify the data element for the LOW and HIGH component. The ID_PERSON has the data type YIDI (Fig. 13.24).
Fig. 13.24 Database table YPERSON
A Range Table has four components: SIGN, OPTION, LOW and SCREEN. It can be also created in the ABAP Dictionary, as special type of table types. The method ADD_SELECTION_FIELD of the IF_WD_SELECT_OPTIONS interface adds an additional Field to the Selection Screen. This method has many parameters, but only one is mandatory – I_ID. We have used the: l l l l l
l l
i_id parameter, of STRING type, to define the ID of the Selection Field i_obligatory parameter, of ABAP_BOOL type, to set the mandatory field it_result parameter, type ref to data, for reference to the Range table i_tooltip, of STRING type, to create a quick info in a tooltip form i_value_help_type, of type: IF_WD_VALUE_HELP_HANDLER)CO_PREFIX_ NONE to specify the type of the search help that we want to use i_value_help_id of WDY_VALUE_HELP_ID type, to specify the name of the search help that we use, or the name of the OVS (Object Value Selector) component. In our case, the field ID_PERSON has associated the search help with the name YSH_ID_PERSON
When the user presses the Search button, the Framework triggers the event handler method onactionsearch (Listing 13.7).
310
13 ALV and Select Options METHOD onactionsearch . DATA: l_node TYPE REF TO
if_wd_context_node. rt_range_table TYPE REF TO data. DATA: it_yperson TYPE TABLE OF yperson. FIELD-SYMBOLS : TYPE ANY TABLE. rt_range_table = wd_this->m_handler->get_range_table_of_sel_field( i_id = 'ID_PERSON' ). ASSIGN rt_range_table->* TO . CLEAR it_yperson. REFRESH it_yperson. SELECT * INTO CORRESPONDING FIELDS OF TABLE it_yperson FROM yperson WHERE id_person IN . l_node = wd_context->get_child_node( name = `PERSON` ). l_node->bind_elements( it_yperson ). ENDMETHOD. DATA:
Listing 13.7 The onactionsearch event handler method
The method GET_RANGE_TABLE_OF_SEL_FIELD of the IF_WD_ SELECT_OPTIONS interface has an importing parameter I_ID, of STRING type, and returns the range table for the Selection Field – rt_range_table generic type data. We define a field symbol typified as ANY TABLE and we generically dereference the data reference variable typed with data into our field symbol, through the dereferencing operator “!*”. After this, we select all the records that correspond to our search and pass these values in the corresponding attributes of the context node PERSON. We have to embed the interface view WND_SELECTION_SCREEN into the ViewContainerUIElement. Now we are ready to run our application (Fig. 13.25).
Fig. 13.25 Embedding the view interface WND_SELECTION_SCREEN
The runtime result is presented in Fig. 13.26.
13.2 Select Options
311
Fig. 13.26 Runtime
In default mode, Select Option is the interval between two values, but we can also use other Select options (Fig. 13.27).
Fig. 13.27 Selecting options
As we have seen, the component WND_SELECTION_SCREEN offers four buttons to provide four functions: l l l l
Cancel Check Reset Execute
We can hide one of these buttons by using the method SET_GLOBAL_OPTIONS of the IF_WD_SELECT_OPTIONS interface. This method has four mandatory parameters of ABAP_BOOL type (Fig. 13.28).
312
13 ALV and Select Options
Fig. 13.28 The SET_GLOBAL_OPTIONS parameters
We want to extend our example, by hiding the buttons CANCEL, RESET, COPY and using the CHECK button to trigger the event handler method on_check. In this case, we don’t use our Search button. We implement the code in the on_check event handler method. First, we must use, in the wdDoInit Hook method, the SET_GLOBAL_OPTIONS (Listing 13.8). wddoinit . ………………. wd_this->m_handler = wd_this->m_wd_select_options->init_selection_screen( ). wd_this->m_handler->set_global_options( i_display_btn_cancel = abap_false i_display_btn_check = abap_true i_display_btn_reset = abap_false i_display_btn_execute = abap_false ). …………………… ENDMETHOD . METHOD
Listing 13.8 The wdDoInit Hook method
After this, we create an event handler method named on_check and we register to the ON_CHECK event in the WDR_SELECT_OPTION component (Fig. 13.29). This event is triggered when the user clicks the CHECK button.
Fig. 13.29 Registering to the ON_CHECK event
13.3 ALV and Select Options
313
We copy the entire coding from the onactionsearch event handler method in the on_check event handler method, and then we can run our application (Fig. 13.30).
Fig. 13.30 Runtime
To create more than one selection screens Field, we have to create, into the wdDoInit Hook Method, as many range tables as many screen Fields we need, and then we have to extend the event handler method to be able to select the desired data.
13.3
ALV and Select Options
In this case, we use both components: WDR_SELECT_OPTIONS for Select option and SALV_WD_TABLE for ALV (Fig. 13.31).
Fig. 13.31 Used components
We copy the preceding WD component and rename it: Y_ALV_AND_SO. Here we made only some changes:
314 l l
l l l
13 ALV and Select Options
Create the context node in the COMPONENTCONTROLLER Delete the Table UI element and insert a new ViewContainerUIElement required to embed the Table interface view Define the required usages; Define the required context mappings; Check if the instance of the used component ALV_USAGE is made. If it doesn’t exist, we have to create one. The View layout has the structure presented in the Fig. 13.32.
Fig. 13.32 View Layout
The window structure is presented in Fig. 13.33.
Fig. 13.33 Window structure
The runtime is presented in Fig. 13.34.
Fig. 13.34 ALV and SO
Chapter 14
Integrating a Web Dynpro Application into the SAP NetWeaver Portal
“Learn from yesterday, live for today, hope for tomorrow. The important thing is not to stop questioning.” Albert Einstein
Abstract The present chapter is mainly dedicated to the presentation of the modality to integrate the Web Dynpro applications in the portal, by using the SAP NetWeaver Portal. In the same time, we show how we can communicate between two applications by using the portal eventing (event sender and event receiver). SAP NetWeaver Portal offers many possibilities to create its content, from Wizards and templates, to applications developed in Web Dynpro ABAP or Web Dynpro Java. Our scope is to integrate into the portal a created Web Dynpro ABAP application named y_ui_contextualpanel. After this, we create a Web Dynpro component that can send a portal event, a Web Dynpro component that can react to a portal event and, finally, we integrate the created applications in the Portal. To access the portal, we have to navigate to the portal home page (for example, URL: http://hostname:50000/irj), and to use its initial screen to login. After a successful log-in (with a portal user that has the proper authorizations), we have to connect to the back-end ABAP system, because our Web Dynpro applications are developed in the ABAP system. For the first example, we create an iView required to integrate our application, we create a portal Role and we assign it to the user that needs to access the Web Dynpro application. In order to process the portal events, after we develop the Web Dynpro components and integrate the applications into the two iViews, we create a portal Page, we assign the iViews to our page, the page to a role and the role to the user. In order to communicate between two applications, even if these applications don’t use the same technologies or run on different systems, we can use the Portal Eventing (event sender and event receiver), with one condition: the applications to be integrated in two portal iViews.
U. Gellert and A.D. Cristea, Web Dynpro ABAP for Practitioners, DOI 10.1007/978-3-642-11385-7_14, # Springer-Verlag Berlin Heidelberg 2010
315
316
14 Integrating a Web Dynpro Application into the SAP NetWeaver Portal
To realize the actual applications, we used a portal user that owns all the required authorizations, including the authorization to create roles and to assign by the created roles. In practice, such authorizations combined for one single user are used only for the testing systems; in the real systems, the attributions of the administrators (e.g. user administrator, content administrator, system administrator) are very well defined (separated). In the same time, a user that doesn’t own administrative roles can access only those functionalities that have been assigned to him by the administrator. Tip For more information about the Portal, please refer to the SAP PRESS book, SAP NetWeaver Portal (Niculescu et al.)
14.1
Creating a Folder
We begin our exercise with the creation of a folder to be used to hold all the subsequently created portal objects. Into the Portal Catalogue, we create a folder named Book. To perform this operation, we have to open the contextual menu (by right-clicking on the folder where we want to create our folder) and to choose New ! Folder. A wizard is open (Fig. 14.1) and we can create it.
Fig. 14.1 Creating a new folder
14.2 Connecting to the Back-End ABAP System
317
As we can see, we have to enter some information, as follows: l l l
l
Folder Name – the name of the new created folder Folder ID – unique identifier for the new created folder Master Language – the original language for all the portal objects subsequently created in this folder Description – brief description of the newly created folder
After saving the information, the Framework generates the created book folder into the Portal Catalogue. In order to set other properties for it, we can use the available wizard. We have to mention that the book folder inherits the permissions from its parent folder.
14.2
Connecting to the Back-End ABAP System
In the next step, we connect to the back-end ABAP system. To do this, we create a new System: System Administration ! System Configuration ! System Landscape that opens the System Landscape Editor. Here, we navigate to our book folder and open the contextual menu, by right-clicking. By using New ! System (from template), a Wizard is open and offers the possibility to define a new system through some easy steps (Fig. 14.2).
Fig. 14.2 Creating a new system
In the first wizard step, we have to choose a template (Fig. 14.3). In the next step, we have to enter general properties, as follows: System Name, System ID, Master Language, Description (Fig. 14.4).
318
14 Integrating a Web Dynpro Application into the SAP NetWeaver Portal
Fig. 14.3 Template selection
Fig. 14.4 General properties
14.2 Connecting to the Back-End ABAP System
319
After this, we can open the object editor and configure our system. We start with the Property Category named Web Application Server (Web AS) (Fig. 14.5).
Fig. 14.5 Web application server property category
For the next configuration, we navigate to the Connector Property Category required to realize the configuration:
, the hostname;
, the SAP client from back-end;
, specifies the system number we want to connect to;
, specifies the system ID we want to connect to;
, the server port;
, the system type.
320
14 Integrating a Web Dynpro Application into the SAP NetWeaver Portal
In the next configuration, we go to User Management Property Category (Fig. 14.6) required to set the mode the users log-on to our ABAP backend system.
Fig. 14.6 User management property category
As Logon Methods, we have used the SAPLOGONTICKET. Each system must have at least one system alias, a name defined by the system administrator, required to refer the specified system. By using the System Aliases tool, we set an alias name for our ABAP backend system (Fig. 14.7).
Fig. 14.7 Creating an alias name for our ABAP system
Now, we are able to test our system configuration by using the Connection test tool (Fig. 14.8).
14.3 Creating an iView
321
Fig. 14.8 Testing the connection to the ABAP system
In case a system configuration for the ABAP back-end already exists, we don’t need to create another one.
14.3
Creating an iView
An iView (integrated View) represents the smallest element we can create into the SAP NetWeaver Portal. In our case, we use an iView to integrate our Web Dynpro application. To create a new iView into our book folder, we have to navigate to the Content Administration ! Portal Content and, by right-clicking on the folder name, we open the contextual menu (Fig. 14.9). The Portal Content Studio represents the central environment we can use to create the portal content.
Fig. 14.9 Creating an iView into our book folder
Through a Wizard, we have the possibility to create a new iView, by using: l l l
iView template; Portal content; Web Dynpro Java application.
322
14 Integrating a Web Dynpro Application into the SAP NetWeaver Portal
We choose the first option – iView template, because our scope is to integrate the Web Dynpro ABAP application into the portal. In the next Wizard step, we can choose a template from the available template list. Here, we find many templates, e.g. URL iView (used to integrate a Website into the portal), SAP Transaction (iView used to show a SAP transaction into the portal), SAP Web Dynpro iView (required to integrate a Web Dynpro ABAP or Java application). (Fig. 14.10)
Fig. 14.10 Selecting a template from the existing template list
In the next step, we have the possibility to provide the iView General Properties, as follows: l l l l
iView Name – the iView name displayed in Portal Catalogue, etc.; iView ID – unique identifier for the created iView; Master Language – the original language the properties are generated in; Description – optional description (Fig. 14.11).
14.3 Creating an iView
323
Fig. 14.11 iView general properties
In the next Wizard step, we can choose between the integration of a Web Dynpro ABAP application or a Web Dynpro Java application (Fig. 14.12).
Fig. 14.12 Web Dynpro for ABAP iView
In the last step, we enter the parameters of our Web Dynpro ABAP application (Fig. 14.13). When we press the Finish button, the Framework starts to process the provided information and generates the proper iView. We can test our Web Dynpro application by choosing Preview from the contextual menu (Fig. 14.14).
324
14 Integrating a Web Dynpro Application into the SAP NetWeaver Portal
The system defined above
The name of the WD application (created in ABAP back-end) that we want to integrate into the iView
Fig. 14.13 Web Dynpro parameters
Generated iView
Fig. 14.14 Testing the iView
14.4
Creating a Role and Role Assignment
By using a role, we can specify which services can be accessed by a user or a group of users, and we can define which content can be seen in the portal by the respective user or user group. In this example, we create a portal role. In the next chapter, we’ll see how we can create a role in the ABAP back-end system to grant delete capability for the database table YPERSON through a Web Dynpro application.
14.4 Creating a Role and Role Assignment
325
In the book folder, we create the role by using the contextual menu New ! Role (Fig. 14.15).
Fig. 14.15 Creating a role
As a result, the Wizard generates a newly created role:
By using the Delta Link concept, we can assign the iView to our new role (Fig. 14.16).
Fig. 14.16 Assigning iView to role, by using the Delta Link concept
326
14 Integrating a Web Dynpro Application into the SAP NetWeaver Portal
As a result, we can see the created assignment:
Then, we assign the created portal role to our test user Gellert. In order to realize this assignation, we access User Administration ! Identity Management and search for our test user (Fig. 14.17).
GELLERT
GELLERT
GELLERT , ULLI
ABAP
Fig. 14.17 Searching for a user
We select the user and, as a result, in the lower part of the screen we can see the details of the selected user. By using the Modify button, we can add the newly created role to the respective user (Fig. 14.18). GELLERT
Fig. 14.18 Assigning a portal role to the Gellert user
14.6 Triggering a Portal Event
327
By using the Add button, we attach the role (after selection) to the list of roles assigned to this user.
14.5
Running the Application into the Portal
In order to see the top-level navigation and the page defined in the assigned role, we save our changes, we logoff and then we login again. After logging-in, we can see in the upper part of the screen, on the main navigation bar, the new item named CONTEXTUALMENU UI element, corresponding to our newly attached role. Figure 14.19 shows the running application into the portal.
Fig. 14.19 Web Dynpro running application into the portal
14.6
Triggering a Portal Event
Web Dynpro through the Portal – Manager offers some methods to be used to trigger events and to react to portal events. To do this, we can use the methods of the IF_WD_PORTAL_INTEGRATION interface, as follows: l l l
FIRE – Trigger portal event; SUBSCRIBE_EVENT – Register portal event; UNSUBSCRIBE_EVENT – Delete portal event registration.
For the scope of this example, we re-create our firstly created component; but, in this case, we enter the name in the Web Dynpro component that triggers the portal event and we display the greeting in the second Web Dynpro component that reacts to the portal event (Fig. 14.20). The Portal Eventing concept is appropriate for communication between applications created by using different technologies. But, through this example, we will create the application that triggers the portal eventing and the application that react to the portal event by using the same technology, Web Dynpro ABAP. Our purpose is to present the both cases and, depending on the requirements, to choose one of the variants (trigger or receiver) in combination with
328
14 Integrating a Web Dynpro Application into the SAP NetWeaver Portal
SAP NetWeaver Portal Page
Portal Events
Web Dynpro ABAP application – event trigger Web Dynpro ABAP application, reacting to portal event
Fig. 14.20 Processing portal events
an application developed into another technology (Web Dynpro Java, Visual Composer, etc.). We start with the creation of the Web Dynpro component able to trigger a portal event by using the FIRE method. The structure of this component and the view layout are presented in Fig. 14.21.
Fig. 14.21 Web Dynpro component structure and view layout
In the context view, we have created an attribute named “NAME”, of STRING type. When the user presses the “Event trigger” button, we use the FIRE method to trigger a portal event that will be subsequently passed by the portal to the second iView that has been registered for this event, respective to the second Web Dynpro ABAP application. In this way, the events can be transported between the iViews (Web Dynpro applications or applications that use other technologies). Listing 14.1 shows the coding of the onactionevent_trigger event handler method. As we can see, after passing the value of the context attribute into the local variable LV_NAME, we use the FIRE method of the IF_WD_PORTAL_INTEGRATION
14.7 Reacting to a Portal Event
329
METHOD onactionevent_trigger . DATA lv_name TYPE string. wd_context->get_attribute( EXPORTING name = `NAME` IMPORTING value = lv_name ). DATA: lr_api_component TYPE REF TO if_wd_component, lr_portal_manager TYPE REF TO if_wd_portal_integration. lr_api_component = wd_comp_controller->wd_get_api( ). lr_portal_manager = lr_api_component->get_portal_manager( ). lr_portal_manager->fire( portal_event_namespace = 'sap.example' portal_event_name = 'person_name' portal_event_parameter = lv_name ). ENDMETHOD.
Listing 14.1 onactionevent_trigger event handler method
interface to fire the portal event with the name “person_name”. This method has three importing parameters of STRING type: l l l
PORTAL_EVENT_NAMESPACE – namespace in which the event is stored; PORTAL_EVENT_NAME – name of the event; PORTAL_EVENT_PARAMETER – parameter.
These values have to match with the event receiver application. Web Dynpro Wizard offers the required support to work with portal events (Fig. 14.22).
Fig. 14.22 Web Dynpro Wizard and portal manager
14.7
Reacting to a Portal Event
Now, we are creating the Web Dynpro application able to react to the event triggered in the first iView in the portal. The structure of this component, the view layout and the context view are presented in Fig. 14.23.
Fig. 14.23 Web Dynpro component structure, view layout and context view
330
14 Integrating a Web Dynpro Application into the SAP NetWeaver Portal
In the context view, we need only the attribute “NAME”, where we pass the parameter value concatenate with a WELCOME string. To be capable to register our Web Dynpro application for a portal event, we have to use the SUBSCRIBE_EVENT method of the same IF_WD_PORTAL_INTEGRATION interface. This method shall be used into the wdDoInit Hook Method (Listing 14.2).
METHOD wddoinit . DATA lr_api_component TYPE REF TO if_wd_component. DATA lr_portal_manager TYPE REF TO if_wd_portal_integration. lr_api_component = wd_comp_controller->wd_get_api( ). lr_portal_manager = lr_api_component->get_portal_manager( ). DATA lr_api_controller TYPE REF TO if_wd_view_controller. lr_api_controller ?= wd_this->wd_get_api( ). lr_portal_manager->subscribe_event( portal_event_namespace = 'sap.example' portal_event_name = 'person_name' view = lr_api_controller action = ‘EVENT_RECEIVER’ ). ENDMETHOD.
Listing 14.2 The wdDoInit Hook method
The SUBSCRIBE_EVENT method has three parameters of STRING type and one parameter type ref to IF_WD_VIEW_CONTROLLER. As we can see, this method needs to specify not only the namespace, the name of the event and the view, but also the name of the action to be called when the event occurs. We have created an action named “EVENT_RECEIVER”. The event handler method is presented in Listing 14.3.
METHOD onactionevent_receiver . DATA lv_event_name TYPE string. DATA lv_event_parameter TYPE string.
lv_event_name = wdevent->get_string( name = 'PORTAL_EVENT_NAME' ). IF lv_event_name = 'person_name'. lv_event_parameter = wdevent>get_string( name = 'PORTAL_EVENT_PARAMETER' ). CONCATENATE 'WELCOME' lv_event_parameter INTO lv_event_parameter SEPARATED BY space. wd_context->set_attribute( name = 'NAME' value = lv_event_parameter ). ENDIF. ENDMETHOD.
Listing 14.3 The onactionevent_receiver event handler method
14.8 Creating a Page
331
By using the method GET_STRING (parameter: PORTAL_EVENT_NAME), we pass the value of the portal event name into the local variable lv_event_name. Then, in case this local variable has the value “person_name” (our defined event name), we have to obtain the value of the parameter. By using the method GET_STRING (parameter: PORTAL_EVENT_PARAMETER), we can pass the parameter of the portal event to the action parameter WDEVENT and to our local variable lv_event_parameter. In the last step, we create the greeting and we pass this value in the context attribute.
14.8
Creating a Page
In this case, we need the two iViews to appear in the same screen. This is the reason why we use a Page. Into a portal Page, we can insert iViews or other portal Pages and we can set a proper layout. To create a Page into our book folder, we right-click on the folder name and, from the contextual menu, we choose New ! Page. A Wizard guides us through the required steps to create our first portal Page. In the first step, we have to enter the Page properties (Fig. 14.24).
Fig. 14.24 Page properties Wizard step
In the next step, we have to choose the page template on which to ground the new portal page (here we have chosen “Default Page Template”) and in the last step, before OVERVIEW and SAVE, we choose the layout to be assigned to the page. This layout shows how the content will be arranged (Fig. 14.25).
332
14 Integrating a Web Dynpro Application into the SAP NetWeaver Portal
Fig. 14.25 Page layouts Wizard step
In our book folder, we create two iViews required to integrate our two created Web Dynpro applications. Figure 14.26 shows the structure of the book folder.
Portal Role iViews
Fig. 14.26 Book folder structure
Portal Page
After creating iViews Page, all we have to do is to assign the two iViews: Event sender and Event receiver to our portal Page named “Portal event”. To perform this operation, we use the delta link concept firstly applied when we have assigned the iView to the Role. Now we are able to see the Page Content (Fig. 14.27).
Fig. 14.27 Page content
14.9 Running the Application that Processes Portal Events
14.9
333
Running the Application that Processes Portal Events
All we have to do is to assign the portal Page to our role (through the delta link concept) and to perform a logoff and a new login into the portal. Figure 14.28 shows the runtime result.
Fig. 14.28 Runtime
In case we want to differently arrange the display of the two iViews into the Page, we can use the Page Layout. We can also change the layouts by dragging & dropping and rearrange the iViews that define the content (Fig. 14.29).
Drag and Drop the iView from a column to another column
Fig. 14.29 Page Layout
Chapter 15
Web Dynpro and Authorization
“Only when you will realize that you have wings and understand what they are for you will be able to learn how to fly.” Marie-Suzanne Labelle
Abstract Based on the RBAC (Role Based Access Control) pattern, we are going to present the SAP R/3 role based authorization mode. According to it, a user can dispose of a number of roles, which grants to him/her the authorization to access certain resources from the system. In this respect, we will create the development objects required to grant to the user the possibility to access the records from a database, and we will use, in Web Dynpro ABAP, the declaration AUTHORITYCHECK to verify the current user’s authorization. For standalone Web Dynpro applications, being not integrated in the portal, the security shall be programmed into the application. For the applications that run into the Portal, we can use the Portal security to authenticate and authorize the access to the application. The way we can do this depends on specific situations. For example, we can define in the portal the authorization for the content we offer to the user, but we cannot define the authorization for the backend application itself. This kind of authorization shall be done in back-end, through development objects as authorization fields, authorization object, etc. To check which functions can be executed by the user or which objects can be accessed by him, in backend, through a Web Dynpro application, we can use statements as AUTHORITY-CHECK. These statements are implemented at the program level in our application or into the model used for our application. Now, we create a very simple example to show how we can use an Authorization Object into a Web Dynpro component to check the authorization of the current user and to grant access to the Open SQL delete action for our database table YPERSON. We use a user administrator and a profile administrator to create the object class, the authorization object and the role, and to assign the created role to our test user Gellert. By using our test user, we create the Web Dynpro component and we check his right to perform the desired delete action (Fig. 15.1). U. Gellert and A.D. Cristea, Web Dynpro ABAP for Practitioners, DOI 10.1007/978-3-642-11385-7_15, # Springer‐Verlag Berlin Heidelberg 2010
335
336
15 Web Dynpro and Authorization Authorization to delete the records 004 – 100 from the YPERSON database table
Users
Ui
Ux
Test user “Gellert”
Roles ztest_role
Permissions -> Authorizations: Class, Object, Fields
Rx Ry U – User R – Role (single and composite) AO – Authorization Object AF – Authorization Field AOC – Authorization Object Class
AO - ztest _ auth AF: ACTVT ZAF_PERSON
AOn AFt
AOC
Fig. 15.1 The relationship user – roles – permissions, for our example
An Authorization Object is used to check a user authorization for special activities. Usually, the authorizations are combined into authorization profiles, and these profiles are assigned with a role. Then, a role (single or composite) can be assigned to users, and all the authorization changes affect all the users that have assigned the respective role. The scope of the present chapter is to offer to the reader a general idea about the authorization concept SAP R/3 and about the modality of using this concept to create secure Web Dynpro applications. This is the reason why we chose an example where we could create all the required development elements, even if in practice this requirement appears only occasionally. SAP offers a large range of authorization objects and templates that we can use and customize according to our requirements. In most cases, to grant access to the tables, we use authorization groups (extended authorization for particular objects) and authorization objects, as: S_TABU_DIS, S_TABU_LINE. We have already used an authorization group in Chap. 11, where we have created table maintenance. In that example, we chose from the authorization group list “&NC&” (no security) and we saw that the authorization object has been predefined as S_TABU_DIS. We can assign an authorization object, through the menu Utilities ! Assign Authorization Group, to a view and to a transparent table created in the ABAP Dictionary. Because in our case we offer the capability to delete certain records from the YPERSON table by only one user, the usage of the authorization group has no meaning. Another reason for using the authorization groups in the example was to put forward the basic elements, without entering in the private objects field and, in the same time, to present the authorization field ACTVT we shall meet often during
15.1 Role Based Access Control Pattern – RBAC
337
working with Web Dynpro applications, when we check the authorization for different activities, with tables. Tip For more details about the SAP Authorization concepts, please refer to the book SAP Authorization System by IBM Business Consulting Services
15.1
Role Based Access Control Pattern – RBAC
The Pattern that stays at the basis of the presented concept is the Role Based Access Control pattern, an access control model currently used to develop secure systems. This pattern was firstly formalised by Ferraiolo and Kuhn, in 1992 (the 15th National Computer Security Conference, 1992, Baltimore MD, pages 554–563), in a form that allows the users to access the resources by using roles and permissions, and where the roles can inherit permissions from other roles. Various forms of Role Based Access Control have been created and implemented in a variety of commercial systems. Hereunder, we present a extended form of the RBAC pattern. Pattern Name: Role based access control. Context: Any environment where we need to control the access to resources based on the user’s roles. Problem: How we can assign rights to users in concordance with their roles, so that each user to have only the authorization required to carry out his responsibilities? Solution: In Fig. 15.2 it is presented a class model for the Role Based Access Control. Single Role
Group
Composite Role
* * User
Has assigned
Role
*
*
is authorized for
*
Protected Obiect
* Rights
*
1
Subset * Works on
*
Session.
AdimnRole
AdimnRight
Fig. 15.2 The role based access control pattern Schumacher et al. (2006)
We will explain this concept as regards to the Application Server ABAP. The Class User represents the user that attempts to access the protected object (transactions, programs, services), and the Role class represents the user roles. A role can be a single role or a composite role. The composite role can contain only single roles, and the single role can contain, for example, the logon menu for the user and authorization objects. SAP offers a large number of single roles to be used, but we can also create our own ones. Class Right describes the access type (delete, write, etc.).
338
15 Web Dynpro and Authorization
Each user can be member of a group or more. Through the Session class, it is implemented the principle of “least privilege”, according to which a user gets, through every session, only the privileges required to perform his responsibilities. In our example presented in Fig. 15.1, the profile administrator creates a single role ZTEST_ROLE, assigns to it the authorization object ZTEST_AUTH, maintains the fields and generates the authorization profile. Our test user, Gellert, tries to perform a delete operation in the YPERSON database, but he doesn’t have assigned the ZTEST_ROLE yet. That’s why he doesn’t have the authorization to perform this operation. Only after the user administrator assigns him the role, he can perform the delete operation for the database records found in the range 004–100. So, we have the separation between the role administrator and the right administrator. Besides this basic division, there are other different scenarios that can be used. Applications: J2EE, SAP NetWeaver, Oracle, etc.
15.2
Authorization Object Class
One or more Authorization Objects shall be assigned to a Class. To create a new class, we can use, from the screen “Maintain Authorization Objects” (transaction SU21), the CREATE button (Fig. 15.3).
Fig. 15.3 Creating an object class
15.3
Authorization Object
After creating the class, we can create an Authorization Object directly in the created class (Fig. 15.4) or we can firstly create an Authorization Object and then assigning the Object to the created class (Fig. 15.5).
15.3 Authorization Object
Fig. 15.4 Creating an authorization object
Fig. 15.5 Assigning an Authorization Object to a class
339
340
15.4
15 Web Dynpro and Authorization
Authorization Fields
An Authorization Object can contain maximum ten authorization fields. These fields can be chosen from the list of the existent ones (activities, actions, etc.) or we can create our own authorization fields. Figure 15.6 shows the structure of the Authorization Object named ZTEST_AUTH.
Fig. 15.6 Defining the authorization field
We have chosen to add a field named ACTVT, because we need to check an activity. The possible activities that can be protected are stored in the table TACT that has a 1:CN key relation with the table TACTZ and a txt relationship with the table TACTT. In the table TACTT, there are stored the activities descriptions, and in the table TACTZ there are stored the valid activities for each authorization object (Fig. 15.7).
15.4 Authorization Fields Fig. 15.7 Table TACT and some of its related tables
341
TACT Activities which can be protected
TACTZ 1 : CN KEY
Valid activities for each authorixation objects
TOBJ Authorixation objects
1 : CN KEY
The structure of the table TACT is presented in Fig. 15.8.
Fig. 15.8 Table TACT
As we can see, this table contains all the actions we can use (Fig. 15.9).
Fig. 15.9 Actions from the TACT table
342
15 Web Dynpro and Authorization
From the “Create authorization Object” screen, we can use the button “Field Maintenance” or we can use the SU20 transaction to navigate to the list of the authorization fields (Fig. 15.10).
Fig. 15.10 List of authorization fields
Here, we have created a new field named ZAF_PERSON (Fig. 15.11).
Fig. 15.11 Authorization field
Then, we save the new created Field and go back to our Authorization Object. Here, we insert the ZAF_PERSON and, by using the “Permitted activities” from the end of the screen, we select the Delete activity from the activity list (Fig. 15.12). In case we want to re-use this authorization object in the future, we can tick more activities, and we use for our request only the delete activity.
15.5 Creating a Single Role and Changing its Authorization Data
343
Fig. 15.12 Defining the activities
15.5
Creating a Single Role and Changing its Authorization Data
After creating the Authorization Object, we create a new single role by using the transaction PFCG (Fig. 15.13).
Fig. 15.13 Creating a new role
After this, we change the authorization data for the new created role. To realize it, we use the “Authorizations” tab, the “Maintain Authorization Data and Generate Profiles” area, and the “Change Authorization Data” button (Fig. 15.14). By using the “Menu” tab, we can define fragments from the user menu that can be seen in SAP
344
15 Web Dynpro and Authorization
Easy Access. Because our authorization doesn’t require new transactions or other objects, we don’t use this tab. By using the “User” tab, we can assign users to the role. We will not use this option, but we will add later the new created role to our test user.
Fig. 15.14 Changing authorization data for a role
In this case, we don’t want to use a Template to generate an authorization profile. This is the reason why we choose, from the pup-up window, the button “Do not select templates” (Fig. 15.15).
Fig. 15.15 Choosing the template window
15.5 Creating a Single Role and Changing its Authorization Data
345
For the scope of our example, we manually select our authorization object. We use the “Manually” Button and enter the name of the Authorization Object we have just created (Fig. 15.16).
Fig. 15.16 Manual selection of the authorization
After this, we choose the activity found in our list – “DELETE” (Fig. 15.17).
Fig. 15.17 Choosing the DELETE activity
Then, we choose the range of IDs where the specified DELETE action is enabled to be performed (Fig. 15.18).
Fig. 15.18 Full authorization for IDs
346
15 Web Dynpro and Authorization
We generate the authorization profile by using the Generate button . As a result, we can see our profile that offers the authorization to delete data from the database table YPERSON – records from 004 to 100 (Fig. 15.19).
Fig. 15.19 Generating the profile
15.6
Creating the Web Dynpro Component
Then, we create a WD component named Y_AUTHORIZATION. The component structure is presented in Fig. 15.20.
Fig. 15.20 WD component structure
By using this WD component, we can search for a record in the database table YPERSON and we can delete a record in case the authorization enabled us to perform the desired activity. The view layout and view context structure are presented in Fig. 15.21.
15.6.1
Checking the Authorization of the Current User
When the user presses the Delete button, the Framework triggers the event handler method onactiondelete (Listing 15.1).
15.6 Creating the Web Dynpro Component
347
Fig. 15.21 Context structure and view layout METHOD onactiondelete. DATA: lt_candidate TYPE TABLE OF yperson, lr_node TYPE REF TO if_wd_context_node, lv_id_person TYPE yidi. DATA lr_api_controller TYPE REF TO if_wd_controller. DATA lr_message_manager TYPE REF TO if_wd_message_manager.
lr_api_controller ?= wd_this->wd_get_api( ). lr_message_manager = lr_api_controller->get_message_manager( ). lr_node = wd_context->get_child_node( 'DELETE' ). lr_node->get_attribute( EXPORTING name = 'ID_PERSON' IMPORTING value = lv_id_person ). AUTHORITY-CHECK OBJECT 'ZTEST_AUTH' ID 'ACTVT' FIELD '06' ID 'ZAF_PERSON' FIELD lv_id_person. IF sy-subrc EQ 0. DELETE FROM yperson WHERE id_person = IF sy-subrc EQ 0.
lv_id_person.
lr_message_manager->report_t100_message( msgid = 'YCL_T100_MSG' msgno = '004' msgty = 'S' ). ENDIF. ELSE. lr_message_manager->report_t100_message( msgid = 'YCL_T100_MSG' msgno = '003' msgty = 'E' ). ENDIF. ENDMETHOD.
Listing 15.1 The onactiondelete event handler method
348
15 Web Dynpro and Authorization
As we can see, we have implemented an authorization check before performing the delete action. AUTHORITY-CHECK OBJECT ’ZTEST_AUTH’ ID ‘ACTVT’ FIELD ‘06’ ID ‘ZAF_PERSON’ FIELD lv_id_person. In this way, we check the authorization of the current user. We can have minimum one and maximum ten authorization fields with specified IDs. In this case, we have the ACTVT and our own created authorization field ZAF_PERSON. For each authorization field, we can specify a value to be checked or we can use the additional DUMMY to avoid checking the respective field. The check is successful only if all the conditions are fulfilled: the field ACTVT (Activity) with the permissible value 06 (Delete) AND the field “ZAF_PERSON” whose permissible value is one of the IDs from 004 to 100. If the check is successful, the sy-subrc = 0; otherwise, it is set to a value not equal with 0: 4 – Authorization check not successful. 12 – No authorization was found for the authorization object. 24 – Incorrect authorization fields or an incorrect number of authorization fields was found. In the Message Class YCL_T100_MSG, we have defined two messages with the IDs 003 and 004, required to show the success message, or the error message in case the action is not allowed. We have created a role ZTEST_ROLE, but we haven’t assigned it to our user. This is the reason why, at runtime, we are not allowed to delete the record with the ID “004”. Figure 15.22 shows the User Interface at runtime.
Fig. 15.22 Runtime
In case we don’t have a certain authorization, as developer for fulfilling the required tasks, we can use the transaction SU53 to find what authorization is missing and to inform the administrator about it. After receiving an exception message caused by a failed authorization, we have to use the specified transaction and to make a screenshot for the administrator. For example, if we try to use the
15.6 Creating the Web Dynpro Component
349
transaction SE11 and we don’t have the proper authorization, in the transaction SU53 we will see the object class, the authorization object and the authorization field we need (Fig. 15.23). The transaction ST01 offers the possibility to create a system trace to find the missing authorization objects.
Fig. 15.23 The missing authorization check
15.6.2
Assigning the User-Role and Running the Application
To be able to perform the delete action, we have to assign the created role to the user that needs to perform this action (In our case, the test user Gellert). By using the transaction SU01, we have the possibility to change user master records (e.g. change, lock or unlock, change his password), to delete user master records or to create a new user (directly or by copying an existing one) (Fig. 15.24).
Fig. 15.24 User maintenance Change
In the tab “Roles”, we can assign our created role ZTEST_ROLE to the test user (Fig. 15.25).
Fig. 15.25 Assigning the role “ZTEST_ROLE” to our test user
350
15 Web Dynpro and Authorization
We run again our Web Dynpro application. The authorization rights become effective and our test user can perform the delete action for the records 004–100 from the database table YPERSON (Fig. 15.26).
Fig. 15.26 The user is allowed to delete data
In case we are trying to delete a record not included in the range 004–100, we get the same “Not Authorized” message. In this case, the authorization check is performed and the system compares the values entered by the administrator in the authorization profile with the values required by the program. As a result, the check is not successful and he is not allowed to perform this task (Fig. 15.27).
Record out of range 004 - 100
Fig. 15.27 Deleting a record not included in the range 004–100
Other authorization objects, which we often check, are: S_TCODE – to check the authorization to run a transaction S_PROGRAM – to check the authorization to run a program S_RFC – to check the authorization to run a RFC S_TABU_DIS – for table maintenance
Chapter 16
Web Dynpro Mind Map
“Teachers open the door. You enter by yourself.” Chinese proverb
Abstract The main focus of this chapter is the presentation of the Mind Map created on the basis of the elements described in this book. It can be of a real help in summarizing the knowledge, facilitating the learning of the Web Dynpro. Tony Buzan is considered the parent of Mind Map. A Mind Map is a diagram used to structure ideas that assist people in many activity fields. The Mind Maps are mostly used to take notes during meetings or at school, as a good method to summarize the knowledge or to prepare a presentation. More details about the advantages of using Mind Map to learn Web Dynpro can be found in the article: “The Advantages of using Mind Map for learning Web Dynpro” (Cristea et al.).1
16.1
Creating a Mind Map
To create a Mind Map, we start from a central point, in our case the Web Dynpro ABAP. This is the main subject of the Mind Map, and all the subtopics connected through lines with this one represent the key-words or, respectively, the main ideas. In this case, we have created a Mind Map based on the subjects presented in this book. From the UI elements to the Hook Methods and component re-use, this wellstructured Mind Map helps us to learn faster the Web Dynpro ABAP and, in the same time, to imprint in mind the main elements required to learn this technology. In Fig. 16.1 is presented the Mind Map created to facilitate the learning of Web Dynpro ABAP.
1
Cristea, Berdie, Osaci and Chirtoc, The Advantages of using Mind Map for learning Web Dynpro, Computer Applications in Engineering Education, Published online: 19 Feb 2009.
U. Gellert and A.D. Cristea, Web Dynpro ABAP for Practitioners, DOI 10.1007/978-3-642-11385-7_16, # Springer-Verlag Berlin Heidelberg 2010
351
352
16 Web Dynpro Mind Map
For each topic or subtopic, we can attach one or more files containing details regarding the respective subject, examples, images, links, etc. For example, if we look at the UI elements, we can easily see that the UI elements to be used with Web Dynpro are divided in certain categories. In this book, we present the following categories: Layout, Action, Selection, Complex, Graphic and Integration. Each of these categories has some corresponding UI elements. In our case, we introduced only those IU elements we used in this book, but, as mentioned above, they could very easily be extended. To create Mind Maps, we find a large range of software on the market. iMindMap is considered the World’s Official Mind Mapping software endorsed by Tony Buzan. To create this Mind Map, we used Mindjet MindManager that can be downloaded (and tested, as a trial version gratuity) from the URL: http://www. mindjet.com.
16.2
Web Dynpro ABAP Mind Map
Fig. 16.1 Web Dynpro ABAP mind map
Appendix
Bibliography Assig C, Fobbe AH, Niemietz A (2009) Object services in ABAP. SAP Press, Dedham, MA. ISBN 978-3-8362-1404-9 Banner M, Latka B, Spee M, Schroth R (2008) Developer’s guide to SAP NetWeaver portal applications. SAP Press, Dedham, MA. ISBN 978-1-59229-225-7 Daniela CA, Adela B, Mihaela O, Daniel C (2009) The advantages of using mind map for learning web Dynpro. Wiley InterSci J Comput Appl Eng Educ. doi:10.1002/cae.20285 Hauser J, Deutesfeld A, Rehmann S, Sz€ ucs T, Thunn P (2009) SAP interactive forms by adobe. SAP Press, Dedham, MA. ISBN 978-1-59229-245-7 http://www.mindjet.com http://www.sdn.sap.com/irj/sdn IBM Business Consulting Services (2003) SAP authorization system. SAP Press, Dedham, MA. ISBN 978-1-59229-016-1 Keller H, Kr€uger S (2005) ABAP objects. SAP Press, Dedham, MA. ISBN 978-1-59229-079-6 Keller H, Th€ummel WH (2009) Official ABAP programming guidelines. SAP Press, Dedham, MA. ISBN 978-1-59229-290-5 Lorez A, Scho¨ppe G, Consbruch F, Knapp D, Sonnerberg F (2006) SAP-Anwendungen mit adobe flex. SAP Press, Dedham, MA. ISBN 978-3-89842-794-4 Niculescu V, Klappert K, Krcmar H (2008) SAP NetWeaver portal. SAP Press, Dedham, MA. ISBN 978-1-59229-145-8 Raepple M (2008) The developer’s guide to SAP NetWeaver security. SAP Press, Dedham, MA. ISBN 978-1-59229-180-9 Schumacher M, Fernandez-Buglioni E, Hybertson D, Buschmann F, Sommerland P (2006) Security patterns, integrating security and systems engineering. Wiley, New York. ISBN 0-470-85884-2 Whealy C (2007) Inside web Dynpro for java. SAP Press, Dedham, MA. ISBN 978-3-89842-092-5 Wiegenstein A, Schumager M, Schinzel S, Weidemann F (2009) Sichere ABAP Programmierung. SAP Press, Dedham, MA. ISBN 978-3-8362-1357-8
353
354
Appendix
Abbreviation List ABAP ACTVT ADS ALV AS ABAP AS Java BAPI FM I18N iView J2EE LUW MANDT MVC OTR PDF RBAC RFC SDN SO SPRAS SQL UDDI URL WSDL WYSIWYG XML
Advanced business application programming Authorization field – Activity Adobe document service SAP list viewer Application server ABAP Application server java Business application program interfaces Function module Internationalization Integrated view Java platform, enterprise edition Logical unit of work Data element, SAP client field Model view controller Online text repository Portable document format Role based access control Remote function call SAP developer network Select option Data element, language key Structured query language Universal description discovery and integration Uniform resource locator Web service description language What you see is what you get Extensible markup language
Appendix
355
The Authors Ulrich Gellert lives near Heidelberg (Germany). After his graduation as an IT developer and consultant, he was co-founder of S + P LION, in 1985. He has more than 25 years of experience as project leader, consultant, developer and instructor in many different projects ordered by his customers. Since 2003, he is CEO and chairman of the board of S + P LION AG, international IT Consulting Company with more than 500 employees. Many of these employees work directly at S + P LION’s customer SAP. Additionally, he is a member of the supervisory board and business angel at some start-up companies. Ana Daniela Cristea studied computer science at the University of Petros¸ani (Romania), finishing at top of the class. After 4 years of working as an Assistant Professor at the Polytechnic University of Timis¸oara (Romania), she moved to Pforzheim (Germany). She is currently writing her dissertation about “Contribution to creating and developing a new SAP authorization concept based of Qualifications and physical connections through RFID” and works as a SAP Consultant. She is the editor and co-editor of three released books and many articles.
Index
A ABAP Debugger, 27–31 ABAP Dictionary, 33–54 ABAP Editor, 20 ABAP Objects, 219 ABAP Workbench, 11–12 Access control, 337–338 Action, 19 Adobe document service (ADS), 206 Adobe Flex, 15 Adobe LifeCycle Designer, 207 ALV component, 295–301 ALV configuration model, 299 Application Server (AS) ABAP, 1–4 Application Server (AS) Java, 1–4 Assistance class, 222–224, 244, 259 AUTHORITY-CHECK, 335 Authorization, 7 Authorization field, 335–243 Authorization field ACTVT, 336 Authorization group, 336 Authorization object, 335–350 Authorization object S_PROGRAM, 350 Authorization object S_RFC, 350 Authorization object S_TABU_DIS, 350 Authorization object S_TCODE, 350 B Back-end, 315–320 Breakpoint, 27 Build-in type, 35 Business application program interfaces (BAPI), 260–285 BusinessGraphics UI element, 201–206 Business layer, 4
ButtonChoice UI element, 127–132 Button UI element, 71 C Cardinality, 59–64 Cell editor, 165 Child node, 64 Class, 12 Class Builder, 123, 222, 264 Composite role, 337 Container form, 69, 75 Content administrator, 316 Context attribute, 17–67 Context mapping, 67, 72–84 Context menu, 12 Context node, 16, 40, 45, 51, 55–102 ContextualPanel UI element, 152–154 Controller interface, 22, 60 Currency code, 42 D Database table, 12, 38, 52, 91, 151, 201, 222, 225–233, 247 Database view, 48–51, 255 Data binding, 4, 67–78, 95, 138, 157, 199, 216 Data element, 12, 34–41, 240 DataNavigator UI element, 191 Data type, 33–39, 56 Default view, 23, 141–142, 175, 183 Delta link, 325, 332 Dependent node, 55 Dereferencing operator, 310 Diagram View, 4 Direct mapping, 76, 80
357
358 Domain, 35–38, 132, 241–242 DropDownByIndex UI element, 135–138, 199 DropDownByKey UI element, 133–139, 165 Dynamic context menu, 98 Dynamic context node, 89 Dynamic programming, 91, 123–218 E Eclipse, 1 Empty view, 23 End of list, 303 Enhancement category, 39, 43 Event, 19 Event handler method, 19, 109–112, 267 Exception class, 228–235, 261, 265 External context mapping, 72, 76 F Faceless component, 76, 260 Favorites, 6 Field symbol, 310 FileUpload UI element, 215 Fire method, 105–107, 143, 328 FlowLayout, 93, 114–115 Foreign key, 42–44, 249–252 Framework, 17–26, 70, 87 Fully qualified domain name (FQDN), 14 Function group, 261, 274 Function module, 12, 52, 91, 125, 261, 275–285 G GridLayout, 116–119 Group UI element, 15, 69, 114
Index L Label UI element, 16, 92–93 Language key, 226, 248 Layout, 4 LayoutData, 113 Lead selection, 60, 164, 168 LinkToAction UI element, 91–95, 141–144, 172, 268, 305 Lock mechanism, 53 Lock object, 52 Lock table, 53 Logical unit of work (LUW), 273 Logon page, 30–32 M Main package, 12 Maintenance view, 252–254 MatrixLayout, 119 MessageArea UI element, 159–163 Message class, 222, 225–235, 245, 262 Message Manager, 110–111, 162, 212 Microsoft Excel, 298 Mind map, 351 Model view controller (MVC), 1 Multicomponent applications, 260–273 Multilanguage, 237 Multipurpose internet mail extensions (MIMEs), 92 N Navigation Manager, 4
H Hook method, 19, 87–103, 147, 175, 183, 271, 308–313
O Object class, 335, 338, 349 Object navigator, 11, 33, 46 Online text repository (OTR), 228, 243 Outbound plug, 14, 24, 105, 107–112, 142, 182
I Image UI element, 198–201 Inbound plug, 14, 24, 105–112, 143–144 Independent node, 55 InputField UI element, 16–20, 95, 98, 111 Input help, 47–48, 229 InteractiveForm UI element, 207 Interface method, 84 Internal context mapping, 72–75 Internal table, 51, 62, 232, 269, 272 Internationalization (I18N), 237–256 Interval, 36–41 InvisibleElement UI element, 117 iView, 315, 321–333
P Package, 12, 45 PageHeader UI element, 150–152 Page layout, 332 Pattern, 263, 274, 337 Persistence layer, 4 Persistent class, 261 PhaseIndicator UI element, 180 Portal Content Studio, 321 Portal eventing, 315 Portal folder, 316 Portal home page, 315 Portal page, 315 Portal role, 315
Index Portal user, 315 Presentation layer, 4 R RadioButtonGroupByIndex UI element, 137–140 Range table, 308–310 Regex, 159 Regex Toy, 160 Report, 8 Repository object, 12 Reverse mapping, 79–83, 297 RoadMap UI element, 172–173, 180 Role based access control (RBAC), 337 Rootuielementcontainer, 15, 113 RowLayout, 113, 120–121 S SAP client field MANDT, 40 SAP Easy Access, 5 SAP GUI, 8 SAP List Viewer (ALV), 83 SAP NetWeaver Developer Studio, 1 SAP NetWeaver platform, 1 SAP NetWeaver Portal, 315 SAP R/3 authorization concept, 336 SAP Shortcut, 8–9 Search help, 45–48, 233 Select options, 295, 306–314 Self-reference WD_THIS, 22, 108 Service call, 279, 292 Single role, 337 Single values, 36 Structure, 38 Supply function, 51, 60–64, 86–97, 102–103, 138, 157, 164 System administrator, 316, 320 T Table T100, 222 Table TACT, 340 Table TCURC, 38 Table TSTC, 6 Table type, 39 Table UI element, 60 TabStrip UI element, 146–149 Technical settings, 41–43 Test user, 31, 326 Text symbol, 222–223, 244, 260 Text table, 248–250 TextView UI element, 16, 68–72, 132, 165 TimedTrigger UI element, 124 Top of list, 303 Transaction PFCG, 343
359 Transaction SA38, 159 Transaction SE11, 33 Transaction SE14, 45 Transaction SE24, 123 Transaction SE37, 52 Transaction SE38, 159 Transaction SE63, 243 Transaction SE80, 11 Transaction SE91, 225 Transaction SE93, 6 Transaction SICF, 31 Transaction SM30, 219 Transaction SM59, 206 Transaction SMLT, 238 Transaction ST01, 349 Transaction ST22, 227 Transaction SU01, 237 Transaction SU20, 342 Transaction SU21, 338 Transaction SU53, 348 Translate, 85, 238–254 Transparent Container, 15 Transparent table, 6, 45 Tray UI element, 155 Tree UI element, 60, 190 U UI element hierarchy, 14 UI element library, 14 UI element property, 14 Usage, 21, 62, 76, 296–307, User administrator, 316, 335, 338 User-defined instance method, 19, 103 User interface (UI) element, 14, 123–220 V Value table, 36, 38–42 View, 4 ViewContainerUIElement, 4, 75, 140–150, 172–174, 267, 296, 307, 314 View controller, 14 View designer, 14 View layout, 14 ViewSet, 4 W wdDoBeforeAction, 88, 96–98 wdDoExit, 88, 91–98 wdDoInit, 79, 88–98 wdDoModifyView, 88–98, 116–120 wdDoOnContextMenu, 88–98 WDR_SELECT_OPTIONS, 295, 306, 308, 313
360 Web Dynpro ABAP, 4 Web Dynpro Application, 12 Web Dynpro code wizard, 62 Web Dynpro Explorer, 2 Web Dynpro Java, 1
Index Web Dynpro Perspective, 1 Web Service, 206, 283–294 What You See Is What You Get (WYSIWYG), 4 Window, 12