From efbdcfaee5d697c7e5a32fab11eedc83502c12ee Mon Sep 17 00:00:00 2001 From: xinkent Date: Fri, 27 Feb 2026 00:09:43 +0900 Subject: [PATCH 1/3] Add anchor links for individual columns in model pages Resolves #186 Each column row now has an HTML id attribute (`column-`) and a clickable `#` link that appears on hover. Clicking the link updates the URL hash so the link can be shared. When navigating to a URL that contains a `#column-` fragment the matching column is automatically expanded and scrolled into view via `$anchorScroll`. The feature applies to all pages that use the `column-details` directive (model, source, seed, snapshot). --- .../column_details/column_details.html | 17 +++++++++++ .../column_details/column_details.js | 29 +++++++++++++++++-- 2 files changed, 43 insertions(+), 3 deletions(-) diff --git a/src/app/components/column_details/column_details.html b/src/app/components/column_details/column_details.html index 703496754..7f17db81d 100644 --- a/src/app/components/column_details/column_details.html +++ b/src/app/components/column_details/column_details.html @@ -1,3 +1,18 @@ +
@@ -21,12 +36,14 @@
{{ get_col_name(column.name) }} + #
diff --git a/src/app/components/column_details/column_details.js b/src/app/components/column_details/column_details.js index 819c276d7..3c63342d4 100644 --- a/src/app/components/column_details/column_details.js +++ b/src/app/components/column_details/column_details.js @@ -6,7 +6,7 @@ const _ = require('underscore'); angular .module('dbt') -.directive('columnDetails', ['project', function(projectService) { +.directive('columnDetails', ['project', '$location', '$anchorScroll', '$timeout', function(projectService, $location, $anchorScroll, $timeout) { return { scope: { model: '=', @@ -14,11 +14,35 @@ angular templateUrl: template, link: function(scope) { + scope.column_anchor = function(column, $event) { + $event.stopPropagation(); + $location.hash('column-' + column.name); + if (scope.has_more_info(column)) { + column.expanded = true; + } + } + + scope.$watch('model.columns', function(columns) { + if (!columns || _.isEmpty(columns)) return; + var hash = $location.hash(); + if (!hash || hash.indexOf('column-') !== 0) return; + var col_name = hash.substring('column-'.length); + var target = _.find(columns, function(col) { + return col.name === col_name || col.name.toLowerCase() === col_name.toLowerCase(); + }); + if (target && scope.has_more_info(target)) { + target.expanded = true; + } + $timeout(function() { + $anchorScroll(); + }, 0); + }); + scope.has_test = function(col, test_name) { var test_types = _.pluck(col.tests, 'short'); return test_types.indexOf(test_name) != -1; } - + scope.has_constraint = function(col, constraint_name) { if (!col.hasOwnProperty('constraints')) { return false; @@ -67,4 +91,3 @@ angular } } }]); - From 2d995a77002a82960ec2d96df71f164c687181fb Mon Sep 17 00:00:00 2001 From: xinkent Date: Fri, 27 Feb 2026 00:21:11 +0900 Subject: [PATCH 2/3] Add changelog entry for column anchor links --- .changes/unreleased/Docs-20260227-120000.yaml | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .changes/unreleased/Docs-20260227-120000.yaml diff --git a/.changes/unreleased/Docs-20260227-120000.yaml b/.changes/unreleased/Docs-20260227-120000.yaml new file mode 100644 index 000000000..950fe42fe --- /dev/null +++ b/.changes/unreleased/Docs-20260227-120000.yaml @@ -0,0 +1,6 @@ +kind: Docs +body: Add anchor links for individual columns in model pages +time: 2026-02-27T12:00:00.000000+09:00 +custom: + Author: xinkent + Issue: "186" From 334cb52e431ce705cb9123fa986048cf8c90e0fc Mon Sep 17 00:00:00 2001 From: xinkent Date: Fri, 27 Feb 2026 12:08:13 +0900 Subject: [PATCH 3/3] Fix scroll position to account for sticky header offset --- .../components/column_details/column_details.js | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/app/components/column_details/column_details.js b/src/app/components/column_details/column_details.js index 3c63342d4..3ebfe9f4e 100644 --- a/src/app/components/column_details/column_details.js +++ b/src/app/components/column_details/column_details.js @@ -6,7 +6,7 @@ const _ = require('underscore'); angular .module('dbt') -.directive('columnDetails', ['project', '$location', '$anchorScroll', '$timeout', function(projectService, $location, $anchorScroll, $timeout) { +.directive('columnDetails', ['project', '$location', function(projectService, $location) { return { scope: { model: '=', @@ -33,9 +33,17 @@ angular if (target && scope.has_more_info(target)) { target.expanded = true; } - $timeout(function() { - $anchorScroll(); - }, 0); + // Adjust scroll after model controller's $anchorScroll() completes + // Use native setTimeout to avoid triggering an Angular digest cycle + setTimeout(function() { + var el = document.getElementById(hash); + if (!el) return; + var appScroll = el.closest('.app-scroll'); + var stickyHeader = appScroll && appScroll.querySelector('.app-sticky'); + if (appScroll && stickyHeader) { + appScroll.scrollTop -= stickyHeader.offsetHeight; + } + }, 200); }); scope.has_test = function(col, test_name) {