Skip to content
This repository was archived by the owner on Aug 29, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ This project adheres to [Semantic Versioning](http://semver.org/).
## [0.24.1]
### Fixed
- Improved DatePickerRange, fixing issues [#209](https://github.com/plotly/dash-core-components/issues/209) and [#152](https://github.com/plotly/dash-core-components/issues/152)
- Link component now is a proper <a> tag so you can right click on it, and will scroll back to top. Fixes [#99](https://github.com/plotly/dash-core-components/issues/99), implemented in [#215](https://github.com/plotly/dash-core-components/pull/215)
- Added `max_interval` prop to `Interval` component, fixing issue [#222](https://github.com/plotly/dash-core-components/issues/222)


## [0.24.0]
### Added
Expand Down
2 changes: 1 addition & 1 deletion dash_core_components/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
'external_url': (
'https://unpkg.com/dash-core-components@{}'
'/dash_core_components/bundle.js'
).format(__version__),
).format('0.23.1-rc1'),
'namespace': 'dash_core_components'
}
]
Expand Down
27 changes: 27 additions & 0 deletions dash_core_components/bundle.js

Large diffs are not rendered by default.

7 changes: 6 additions & 1 deletion dash_core_components/metadata.json
Original file line number Diff line number Diff line change
Expand Up @@ -1689,7 +1689,12 @@
"name": "updateLocation",
"docblock": null,
"modifiers": [],
"params": [],
"params": [
{
"name": "e",
"type": null
}
],
"returns": null
}
],
Expand Down
31 changes: 17 additions & 14 deletions src/components/Link.react.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,14 @@ import React, {Component} from 'react';
* event polyfill for IE
* https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent
*/
function CustomEvent (event, params) {
function CustomEvent(event, params) {
params = params || {
bubbles: false,
cancelable: false,
detail: undefined
};
var evt = document.createEvent('CustomEvent');
evt.initCustomEvent(
event, params.bubbles, params.cancelable, params.detail);
evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail);
return evt;
}
CustomEvent.prototype = window.Event.prototype;
Expand All @@ -27,28 +26,32 @@ export default class Link extends Component {
this.updateLocation = this.updateLocation.bind(this);
}

updateLocation() {
const {href, refresh} = this.props;
updateLocation(e) {
e.preventDefault(); // prevent anchor from updating location
const { href, refresh } = this.props;
if (refresh) {
window.location.pathname = href;
} else {
window.history.pushState({}, '', href);
window.dispatchEvent(new CustomEvent('onpushstate'));
}
window.scrollTo(0, 0); // scroll back to top
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very sweet. For some reason I thought we would need to do this after the content was updated, but after playing around with it seems like this totally works 👏

}

render() {
const {className, style, id} = this.props;
const { className, style, id, href } = this.props;
/*
* ideally, we would use cloneElement however
* that doesn't work with dash's recursive
* renderTree implementation for some reason
*/
* ideally, we would use cloneElement however
* that doesn't work with dash's recursive
* renderTree implementation for some reason
*/
return (
<a id={id}
className={className}
style={style}
onClick={this.updateLocation}
<a
id={id}
className={className}
style={style}
href={href}
onClick={e => this.updateLocation(e)}
>
{this.props.children}
</a>
Expand Down
52 changes: 52 additions & 0 deletions test/test_integration.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@

from .IntegrationTests import IntegrationTests

from multiprocessing import Value

# Download geckodriver: https://github.com/mozilla/geckodriver/releases
# And add to path:
# export PATH=$PATH:/Users/chriddyp/Repos/dash-stuff/dash-integration-tests
Expand Down Expand Up @@ -494,6 +496,56 @@ def update_pathname(n_clicks, current_pathname):
self.wait_for_text_to_equal('#test-hash', '')
self.snapshot('link -- /test/pathname/a?queryA=valueA')

def test_link_scroll(self):
app = dash.Dash(__name__)
app.layout = html.Div([
dcc.Location(id='test-url', refresh=False),

html.Div(id='push-to-bottom', children=[], style={
'display': 'block',
'height': '200vh'
}),
html.Div(id='page-content'),
dcc.Link('Test link', href='/test-link', id='test-link')
])

call_count = Value('i', 0)

@app.callback(Output('page-content', 'children'),
[Input('test-url', 'pathname')])
def display_page(pathname):
call_count.value = call_count.value + 1
return 'You are on page {}'.format(pathname)

self.startServer(app=app)

#callback is called twice when defined
self.assertEqual(
call_count.value,
2
)

# test if link correctly scrolls back to top of page
test_link = self.wait_for_element_by_css_selector('#test-link')
test_link.send_keys(Keys.NULL)
test_link.click()
time.sleep(2)

# test link still fires update on Location
page_content = self.wait_for_element_by_css_selector('#page-content')
self.assertNotEqual(page_content.text, 'You are on page /')
self.assertEqual(page_content.text, 'You are on page /test-link')

#test if rendered Link's <a> tag has a href attribute
link_href = test_link.get_attribute("href")
self.assertEqual(link_href, 'http://localhost:8050/test-link')

#test if callback is only fired once (offset of 2)
self.assertEqual(
call_count.value,
2 + 1
)

def test_candlestick(self):
app = dash.Dash(__name__)
app.layout = html.Div([
Expand Down