In this blog I want to introduce a smooth and handy way of navigating in Web Dynpro. I use the following technique in every Web Dynpro application ever since the idea came into my mind. I’m sure you will be able to integrate it in your application and gain the benefit of it.
I do not restrict the guide to WD Java or WD ABAP, it is not relevant how it is programmatically done, the idea itself counts and according to that it is usable for both application servers. Nevertheless I will use some Web Dynpro ABAP screenshots at the details.
Classic navigation in Web Dynpro
Right now the framework offers navigation plugs for navigation as inbound and outbound plugs. The plugs are part of views as entry or exit points. When the user navigates the user will be taken from one view to the next. A typical scenario could be you have two views, View1 and View2 where you have one outbound plug at View1 and one inbound plug at View2 which are connected via a navigation link. The definition of plugs and their navigation links is handled in the applications windows. When an action in View1 is triggered to navigate to View2 the action handler in the view fires the outbound navigation plug. The framework realizes by the navigation link to show View2 now and instantiates the view and calls some handler methods (wdDoInit, handlePlugXy, wdDoModify).
That is basic knowledge and there is no alternative to that of how to navigate between views. Fact is that you will have links between navigation source views and navigation target views. You can only navigate in the views, you cannot fire plugs from controller code. You therefore have a so called point to point navigation. You have to take care that the navigation state, meaning the screen you are in and where you may navigate to, is handled by yourself.
In short form:
- Easy design of navigation
- Simplestructur, easy to understand in small scale
- Navigation only in views
- Hard to maintain when reaching a certain complexity
- No navigation state
Concern of chaos
Before actually going more into detail, there is one scenario which explicitly shows you the need of more control over the navigation. The scenario would be the example from above, having two views in which you can navigate. Now we additionally imagine a third view which is always visible above the two views between we can switch. The third view shows a roadmap UI element which tells us in which screen we are:
When we navigate from one view to the other, the state of the roadmap should change. Now technically the only thing the framework offers is the navigation between the views. What should also be possible is to navigate via the roadmap, by clicking on the target view. What we will need now are more plugs and navigation links.
The more complex your application becomes the more navigations you will most likely have. Now looking beyond three simple views, you might have an application with lots of views where it is possible to switch from one view to all the others. What you will come across is a spider web of navigations you will end up being tangled up in.
Believe it or not, I’ve seen something like that. Now imagine you want to create a new view with all the navigation plugs and links. Probably you have certain restrictions of navigation etc. you will really be in trouble.
There is yet a way for avoiding chaos and gain more control over the navigation.
What I aim for is a way to control complex navigation and make use of the power of the framework. To achieve that I take coding out of the view into the component controller (or custom if you prefer). The idea is to have one view in the whole application which really navigates This one view, I call it navigation view, is the only one with outbound plugs. Still every visible view has its inbound plug of course, but no view will really navigate any more (except navigation view).
This simple idea requires more thinking of course. You have to let the navigation view know that you need to navigate, every source view still needs a way to navigate and the most important are clean up and initialization operations.
The heart of the idea is basically one navigation view which navigates (fires plugs) and two events which are needed to clean up and initialize views: “prepare navigation” and “commit navigation”. The first event will be called if any source view or controller wants to start a navigation from one screen to the next. If every view and controller being involved in that feels fine the navigation will be committed via the “commit navigation” event.
If you have a “dirty flagged” view (changed, unsaved data) for example, you will save it as soon as you get the navigation prepare event. If the saving went fine the commit will be executed. In a usual case the prepare navigation event will come from the source screen. The navigation commit will be called from a controller (component or custom) after the clean up process. When the commit event is called the target step will need to initiate itself and load the data. In case something goes wrong here, you will still keep control of it and navigate back… Let’s see
Every participating view will have one ore more inbound plugs. The navigation view in contrary has several outbound plugs, one to each destination screen. The navigation view must not be a view with UI elements but I usually use one central view which is always visible, you will definitely need to have the view instantiated before you navigate
If a source view wants to navigate (by hitting a next button for example) the view will call a method in a central controller. I usually call the method “prepare_navigation” with the parameter “sourcestep” and if available a parameter “targetstep”. “Targetstep” is usually not necessary the controlling logic of when to navigate where should definitely not be in the view.
The controller then does its clean up logic if necessary and broadcasts out the “prepare navigation” event. Now every controller or view which is active and involved might do his clean up processes. After that the source view itself or any responsible controller will confirm the navigation by calling the “commit_navigation” method in the controller which will broadcast the commit navigation event by passing also the source and now definitely the target step. The navigation view reacts upon the commit event and fires the plug. The target view will do his initialization when receiving the commit event.
The navigation controller (component controller or custom) is responsible for accepting navigation requests and sending out the events. The prepare navigation method and event is intended to take control over the cleaning up, the logic of input validation and things like that. It is also really cool to have the navigation commit method for other uses. You can navigate every time you want from every possible view.
When using good naming conventions you can have a context node with the navigation steps as attributes and make use of it in the views (like road map) and use the constants as step names for dynamic context manipulation and event handling etc.
In case a navigation is not committed nothing happens and in case the target view is not in the mood of displaying because of a faulty state or bad data, the controller or the view itself has the information what the source step was, so the target view can undo the navigation to the initial view if necessary or to an error view.
There is just more control in your code, well structured in methods which are repeating in every control or view.
Introducing the approach to a small application can be fairly easily done and the good thing about it is the scalability. Every new view just fits in the system and will cause the same effort. When you have a huge navigation structure you will experience the power of the Two-Step-Navigation.
When you have applications with sub-steps you can also use the concept – it is just the same behaviour. Even in used components you can make use of it via eventing and method calling.
Using the concept of prepare and commit events as the basis of navigation and not view logic as well as one navigation view as central navigator with outbound plugs makes it very easy to control navigation. You reduce the code fragments to centralized methods and may keep track of the navigation state. When introducing new views to the application they can be easily integrated now and will not cause you hours of searching navigation, validation, clean up and initialization code.
As I mentioned in the beginning it is not restricted to Java or ABAP, I’ve used the concept in projects on both application servers successfully, there is no difference.