diff --git a/public/app/features/templating/templateValuesSrv.js b/public/app/features/templating/templateValuesSrv.js index 46d2f90bc03..5256c3e59b5 100644 --- a/public/app/features/templating/templateValuesSrv.js +++ b/public/app/features/templating/templateValuesSrv.js @@ -27,29 +27,72 @@ function (angular, _, kbn) { var queryParams = $location.search(); var promises = []; + //use promises to delay processing variables that + //depend on other variables. + this.variableLock = {}; + var self = this; + _.forEach(this.variables, function(variable) { + self.variableLock[variable.name] = $q.defer(); + }); + for (var i = 0; i < this.variables.length; i++) { var variable = this.variables[i]; - var urlValue = queryParams['var-' + variable.name]; - if (urlValue !== void 0) { - promises.push(this.setVariableFromUrl(variable, urlValue)); - } - else if (variable.refresh) { - promises.push(this.updateOptions(variable)); - } - else if (variable.type === 'interval') { - this.updateAutoInterval(variable); - } + promises.push(this.processVariable(variable, queryParams)); } return $q.all(promises); }; + this.processVariable = function(variable, queryParams) { + var dependencies = []; + var self = this; + // determine our dependencies. + if (variable.type === "query") { + _.forEach(this.variables, function(v) { + if (templateSrv.containsVariable(variable.query, v.name)) { + dependencies.push(self.variableLock[v.name].promise); + } + }); + } + return $q.all(dependencies).then(function() { + var variableName = variable.name; + var urlValue = queryParams['var-' + variable.name]; + if (urlValue !== void 0) { + return self.setVariableFromUrl(variable, urlValue).then(function() { + self.variableLock[variableName].resolve(); + }); + } + else if (variable.refresh) { + return self.updateOptions(variable).then(function() { + self.variableLock[variableName].resolve(); + }); + } + else if (variable.type === 'interval') { + self.updateAutoInterval(variable); + self.variableLock[variableName].resolve(); + } else { + self.variableLock[variableName].resolve(); + } + }); + }; + this.setVariableFromUrl = function(variable, urlValue) { + if (variable.refresh) { + var self = this; + //refresh the list of options before setting the value + return this.updateOptions(variable).then(function() { + var option = _.findWhere(variable.options, { text: urlValue }); + option = option || { text: urlValue, value: urlValue }; + + self.updateAutoInterval(variable); + return self.setVariableValue(variable, option, true); + }); + } var option = _.findWhere(variable.options, { text: urlValue }); option = option || { text: urlValue, value: urlValue }; this.updateAutoInterval(variable); - return this.setVariableValue(variable, option); + return this.setVariableValue(variable, option, true); }; this.updateAutoInterval = function(variable) { @@ -64,7 +107,7 @@ function (angular, _, kbn) { templateSrv.setGrafanaVariable('$__auto_interval', interval); }; - this.setVariableValue = function(variable, option) { + this.setVariableValue = function(variable, option, firstLoad) { variable.current = angular.copy(option); if (_.isArray(variable.current.value)) { @@ -74,6 +117,11 @@ function (angular, _, kbn) { self.selectOptionsForCurrentValue(variable); templateSrv.updateTemplateData(); + // on first load, variable loading is ordered to ensure + // that parents are updated before children. + if (firstLoad) { + return $q.when(); + } return self.updateOptionsInChildVariables(variable); }; @@ -119,8 +167,7 @@ function (angular, _, kbn) { return datasourceSrv.get(variable.datasource) .then(_.partial(this.updateOptionsFromMetricFindQuery, variable)) - .then(_.partial(this.updateTags, variable)) - .then(_.partial(this.validateVariableSelectionState, variable)); + .then(_.partial(this.updateTags, variable)); }; this.selectOptionsForCurrentValue = function(variable) {