diff --git a/CHANGELOG.md b/CHANGELOG.md
index 60445de8b35..07c1e5bbf5d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,6 +8,7 @@
- Filter editing has gotten its own edit pane with much improved UI and options
- [Issue #296](https://github.com/grafana/grafana/issues/296). Templating: Can now retrieve variable values from a non-default data source
- [Issue #219](https://github.com/grafana/grafana/issues/219). Templating: Template variable value selection is now a typeahead autocomplete dropdown
+- [Issue #760](https://github.com/grafana/grafana/issues/760). Templating: Extend template variable syntax to include $variable syntax replacement
**InfluxDB Breaking changes**
- To better support templating, fill(0) and group by time low limit some changes has been made to the editor and query model schema
diff --git a/src/app/controllers/graphiteTarget.js b/src/app/controllers/graphiteTarget.js
index 23f7cd5b598..5cd1353988c 100644
--- a/src/app/controllers/graphiteTarget.js
+++ b/src/app/controllers/graphiteTarget.js
@@ -165,7 +165,7 @@ function (angular, _, config, gfunc, Parser) {
_.each(templateSrv.variables, function(variable) {
$scope.altSegments.unshift(new MetricSegment({
type: 'template',
- value: '$' + variable.name + ']]',
+ value: '$' + variable.name,
expandable: true,
}));
});
@@ -297,13 +297,7 @@ function (angular, _, config, gfunc, Parser) {
this.value = options.value;
this.type = options.type;
this.expandable = options.expandable;
-
- if (options.type === 'template') {
- this.html = $sce.trustAsHtml(options.value);
- }
- else {
- this.html = $sce.trustAsHtml(this.value);
- }
+ this.html = $sce.trustAsHtml(templateSrv.highlightVariablesAsHtml(this.value));
}
});
diff --git a/src/app/directives/graphiteFuncEditor.js b/src/app/directives/graphiteFuncEditor.js
index db92240bb40..dff8003f54f 100644
--- a/src/app/directives/graphiteFuncEditor.js
+++ b/src/app/directives/graphiteFuncEditor.js
@@ -8,7 +8,7 @@ function (angular, _, $) {
angular
.module('grafana.directives')
- .directive('graphiteFuncEditor', function($compile) {
+ .directive('graphiteFuncEditor', function($compile, templateSrv) {
var funcSpanTemplate = '{{func.def.name}}(';
var paramTemplate = ', ').appendTo(elem);
}
- var $paramLink = $('' + func.params[index] + '');
+ var paramValue = templateSrv.highlightVariablesAsHtml(func.params[index]);
+ var $paramLink = $('' + paramValue + '');
var $input = $(paramTemplate);
paramCountAtLink++;
diff --git a/src/app/partials/panelgeneral.html b/src/app/partials/panelgeneral.html
index 40b46ca0618..c038c807519 100644
--- a/src/app/partials/panelgeneral.html
+++ b/src/app/partials/panelgeneral.html
@@ -10,6 +10,5 @@
-
diff --git a/src/app/services/templateSrv.js b/src/app/services/templateSrv.js
index 9e9dafe2c95..cf76dd5bfaa 100644
--- a/src/app/services/templateSrv.js
+++ b/src/app/services/templateSrv.js
@@ -40,9 +40,27 @@ function (angular, _) {
this._templateData[name] = value;
};
+ this.variableExists = function(expression) {
+ this.regex.lastIndex = 0;
+ var match = this.regex.exec(expression);
+ return match && (self._templateData[match[1] || match[2]] !== void 0);
+ };
+
+ this.highlightVariablesAsHtml = function(str) {
+ if (!str) { return str; }
+
+ this.regex.lastIndex = 0;
+ return str.replace(this.regex, function(match, g1, g2) {
+ if (self._templateData[g1 || g2]) {
+ return '' + match + '';
+ }
+ });
+ };
+
this.replace = function(target) {
if (!target) { return; }
+ this.regex.lastIndex = 0;
return target.replace(this.regex, function(match, g1, g2) {
return self._templateData[g1 || g2] || match;
});
diff --git a/src/css/less/grafana.less b/src/css/less/grafana.less
index d6c4d38f618..01b2004fe11 100644
--- a/src/css/less/grafana.less
+++ b/src/css/less/grafana.less
@@ -479,3 +479,8 @@ select.grafana-target-segment-input {
color: darken(@gray, 25%);
a { color: darken(@gray, 25%); }
}
+
+.template-variable {
+ color: @variable;
+}
+
diff --git a/src/css/less/variables.dark.less b/src/css/less/variables.dark.less
index 605a1672c47..608dfb609b0 100644
--- a/src/css/less/variables.dark.less
+++ b/src/css/less/variables.dark.less
@@ -24,6 +24,7 @@
@orange: #FF8800;
@pink: #FF4444;
@purple: #9933CC;
+@variable: #32D1DF;
// grafana Variables
// -------------------------
diff --git a/src/css/less/variables.light.less b/src/css/less/variables.light.less
index b7cdc5a6271..c3453fdd92b 100644
--- a/src/css/less/variables.light.less
+++ b/src/css/less/variables.light.less
@@ -28,6 +28,7 @@
@orange: #FF7518;
@pink: #E671B8;
@purple: #9954BB;
+@variable: #32D1DF;
// grafana Variables
// -------------------------
diff --git a/src/test/specs/helpers.js b/src/test/specs/helpers.js
index 7293678b6a2..e973058da96 100644
--- a/src/test/specs/helpers.js
+++ b/src/test/specs/helpers.js
@@ -95,6 +95,8 @@ define([
this.replace = function(text) {
return _.template(text, this.data, this.templateSettings);
};
+ this.variableExists = function() { return false; };
+ this.highlightVariablesAsHtml = function(str) { return str; };
this.setGrafanaVariable = function(name, value) {
this.data[name] = value;
};
diff --git a/src/test/specs/templateSrv-specs.js b/src/test/specs/templateSrv-specs.js
index c97f2e2caf4..ecd046ac8fe 100644
--- a/src/test/specs/templateSrv-specs.js
+++ b/src/test/specs/templateSrv-specs.js
@@ -29,6 +29,34 @@ define([
});
});
+ describe('can check if variable exists', function() {
+ beforeEach(function() {
+ _templateSrv.init([{ name: 'test', current: { value: 'oogle' } }]);
+ });
+
+ it('should return true if exists', function() {
+ var result = _templateSrv.variableExists('$test');
+ expect(result).to.be(true);
+ });
+ });
+
+ describe('can hightlight variables in string', function() {
+ beforeEach(function() {
+ _templateSrv.init([{ name: 'test', current: { value: 'oogle' } }]);
+ });
+
+ it('should insert html', function() {
+ var result = _templateSrv.highlightVariablesAsHtml('$test');
+ expect(result).to.be('$test');
+ });
+
+ it('should insert html anywhere in string', function() {
+ var result = _templateSrv.highlightVariablesAsHtml('this $test ok');
+ expect(result).to.be('this $test ok');
+ });
+
+ });
+
describe('updateTemplateData with simple value', function() {
beforeEach(function() {
_templateSrv.init([{ name: 'test', current: { value: 'muuuu' } }]);