Difference between revisions of "AppSuite:Extending the UI (best practices)"

Line 56: Line 56:
 
         // must be a different id than used in original extension
 
         // must be a different id than used in original extension
 
         id: 'compose_preprocess',
 
         id: 'compose_preprocess',
         // important: must be smaller than the one used in original extension
+
         // important: must be smaller than the one used in original extension that is usually 'default'
 
         index: 50,
 
         index: 50,
 
         requires: function (e) {
 
         requires: function (e) {
 
             // is your condition meet?
 
             // is your condition meet?
             if (myCondition = true) {
+
             if (myCondition === true) {
 
                 // stop propagation to suppress execution of
 
                 // stop propagation to suppress execution of
 
                 // requires-handlers of extensions with a higher index
 
                 // requires-handlers of extensions with a higher index
Line 82: Line 82:
 
     // please do not use replace to overwrite 'requires'
 
     // please do not use replace to overwrite 'requires'
 
     ext.point('io.ox/mail/actions/compose').replace({  
 
     ext.point('io.ox/mail/actions/compose').replace({  
        id: 'compose',
 
 
         requires: function () {
 
         requires: function () {
 
             // my custom logic
 
             // my custom logic
Line 89: Line 88:
 
</code>
 
</code>
  
 +
=== scenario: stop propagation of action ===
 +
 +
''simply register a fresh new extension with an index less than the original action extension.''
  
 +
<code>
 +
    // original extension
 +
    new Action('io.ox/mail/actions/compose', {
 +
        index: 100,
 +
        requires: function () {
 +
            return true;
 +
        },
 +
        ...
 +
    });
 +
 +
    // your extension to hide it
 +
    ext.point('io.ox/mail/actions/compose').extend({
 +
        // must be a different id than used in original extension that is usually 'default'
 +
        id: 'compose_preprocess',
 +
        // important: must be smaller than the one used in original extension
 +
        index: 50,
 +
        action: function (baton) {
 +
            // be robust when clicked again and conditions may have changed
 +
            baton.enable('default');
 +
            if (myCondition === true) {
 +
                baton.disable('default');
 +
            }
 +
        }
 +
    });
 +
</code>
 
   
 
   
 
+
'''hint'''
 +
In case the condition for a single action target (f.e. a mail item) do not change you can use 'baton.preventDefault()' alternatively when you condition is met.
  
 
[[Category:AppSuite]]
 
[[Category:AppSuite]]
 
[[Category:UI]]
 
[[Category:UI]]
 
[[Category:Extension points]]
 
[[Category:Extension points]]

Revision as of 06:48, 25 August 2015

API status: In Development

Extension points:
Best practices

Abstract

The extension points system allows different strategies to realize the desired behavior. This is a list of solutions for common scenarios pointing out also some disadvantages of different solutions.


scenario: writing extension in general

separate extension declaration and logic for reusability

  • example: io.ox/mail/common-extensions.js and io.ox/mail/detail/view.js

   var fnProcess = function (baton) { ... };
   // use function within some extension
   ext.point('io.ox/mail/detail/content').extend({
       id: 'links',
       index: 100,
       process: fnProcess
   });
   // use function within another extension
   ext.point('io.ox/mail/detail/content').extend({
       id: 'images',
       index: 100,
       process: fnProcess
   });



scenario: hide/show action

simply register a fresh new extension with an index less than the original action extension.

   // original extension
   new Action('io.ox/mail/actions/compose', {
       id: 'compose',
       index: 100,
       requires: function () {
           return true;
       },
       ...
   });
   // your extension to hide it
   ext.point('io.ox/mail/actions/compose').extend({
       // must be a different id than used in original extension
       id: 'compose_preprocess',
       // important: must be smaller than the one used in original extension that is usually 'default'
       index: 50,
       requires: function (e) {
           // is your condition meet?
           if (myCondition === true) {
               // stop propagation to suppress execution of
               // requires-handlers of extensions with a higher index
               e.stopPropagation();
               // force hide (or force show by using 'return true')
               return false;
           }
       }
   });


unfavorable variants

using ext.point(...).replace

  • original requires function is replaced and can not be accessed anymore
  • also copy and paste it contents does not help cause future changes are not carried over automatically
  • see documentation for .replace

   // please do not use replace to overwrite 'requires'
   ext.point('io.ox/mail/actions/compose').replace({ 
       requires: function () {
           // my custom logic
       } 
   })

scenario: stop propagation of action

simply register a fresh new extension with an index less than the original action extension.

   // original extension
   new Action('io.ox/mail/actions/compose', {
       index: 100,
       requires: function () {
           return true;
       },
       ...
   });
   // your extension to hide it
   ext.point('io.ox/mail/actions/compose').extend({
       // must be a different id than used in original extension that is usually 'default'
       id: 'compose_preprocess',
       // important: must be smaller than the one used in original extension
       index: 50,
       action: function (baton) {
           // be robust when clicked again and conditions may have changed
           baton.enable('default');
           if (myCondition === true) {
               baton.disable('default');
           }
       }
   });

hint In case the condition for a single action target (f.e. a mail item) do not change you can use 'baton.preventDefault()' alternatively when you condition is met.