Browse Source

code-editor: onChange option and usage docs

Alexander Zobnin 8 years ago
parent
commit
152c4170da
1 changed files with 42 additions and 5 deletions
  1. 42 5
      public/app/core/components/code_editor/code_editor.ts

+ 42 - 5
public/app/core/components/code_editor/code_editor.ts

@@ -3,13 +3,22 @@
  * https://github.com/ajaxorg/ace
  *
  * Basic usage:
- * <code-editor content="ctrl.target.query" data-mode="sql" data-show-gutter></code-editor>
+ * <code-editor content="ctrl.target.query" on-change="ctrl.panelCtrl.refresh()"
+ *  data-mode="sql" data-show-gutter>
+ * </code-editor>
+ *
+ * Params:
+ * content:  Editor content.
+ * onChange: Function called on content change (invoked on editor blur, ctrl+enter, not on every change).
  *
  * Some Ace editor options available via data-* attributes:
  * data-lang-mode   - Language mode (text, sql, javascript, etc.). Default is 'text'.
  * data-theme       - Editor theme (eg 'solarized_dark').
  * data-max-lines   - Max editor height in lines. Editor grows automatically from 1 to maxLines.
  * data-show-gutter - Show gutter (contains line numbers and additional info).
+ *
+ * Keybindings:
+ * Ctrl-Enter (Command-Enter): run onChange() function
  */
 
 ///<reference path="../../../headers/common.d.ts" />
@@ -65,15 +74,14 @@ function link(scope, elem, attrs) {
   codeEditor.renderer.setPadding(10);
   setThemeMode(theme);
   setLangMode(langMode);
-
-  codeEditor.setValue(scope.content);
-  codeEditor.clearSelection();
+  setEditorContent(scope.content);
 
   // Add classes
   elem.addClass("gf-code-editor");
   let textarea = elem.find("textarea");
   textarea.addClass('gf-form-input');
 
+  // Event handlers
   editorSession.on('change', (e) => {
     scope.$apply(() => {
       let newValue = codeEditor.getValue();
@@ -81,6 +89,29 @@ function link(scope, elem, attrs) {
     });
   });
 
+  // Sync with outer scope - update editor content if model has been changed from outside of directive.
+  scope.$watch('content', (newValue, oldValue) => {
+    let editorValue = codeEditor.getValue();
+    if (newValue !== editorValue && newValue !== oldValue) {
+      scope.$$postDigest(function() {
+        setEditorContent(newValue);
+      });
+    }
+  });
+
+  codeEditor.on('blur', () => {
+    scope.onChange();
+  });
+
+  // Keybindings
+  codeEditor.commands.addCommand({
+    name: 'executeQuery',
+    bindKey: {win: 'Ctrl-Enter', mac: 'Command-Enter'},
+    exec: () => {
+      scope.onChange();
+    }
+  });
+
   function setLangMode(lang) {
     let aceModeName = `ace/mode/${lang}`;
     fixModuleUrl("mode", lang);
@@ -100,6 +131,11 @@ function link(scope, elem, attrs) {
     let aceThemeName = `ace/theme/${theme}`;
     codeEditor.setTheme(aceThemeName);
   }
+
+  function setEditorContent(value) {
+    codeEditor.setValue(value);
+    codeEditor.clearSelection();
+  }
 }
 
 export function codeEditorDirective() {
@@ -107,7 +143,8 @@ export function codeEditorDirective() {
     restrict: 'E',
     template: editorTemplate,
     scope: {
-      content: "="
+      content: "=",
+      onChange: "&"
     },
     link: link
   };