Skip to content

don't override document.title if set to None - #1343

Merged
chriddyp merged 18 commits into
devfrom
document-title
Jul 27, 2020
Merged

don't override document.title if set to None#1343
chriddyp merged 18 commits into
devfrom
document-title

Conversation

@chriddyp

@chriddypchriddyp commented Jul 23, 2020

Copy link
Copy Markdown
Member

Edit: This feature is now documented in http://dash.plotly.com/external-resources. Look for the title= and update_title=. See the "Customizing Dash's Document or Browser Tab Title", " Update the Document Title Dynamically based off of the URL or Tab", and "Customizing or Removing Dash's "Updating..." Message" sections.

As requested by a Dash Enterprise customer.

This allows users to override document.title during runtime with a
clientside callback or a special component
(plotly/dash-core-components#833)

Example of modifying during runtime:

importdashimportdash_html_componentsashtmlimportdash_core_componentsasdccfromdash.dependenciesimportInput, Outputapp=dash.Dash(__name__, update_title=None)
app.layout=app.layout=html.Div([
dcc.Input(id='input'),
html.Div(id='output'),
html.Div(id='dummy'),
dcc.Tabs(id='tabs-example', value='tab-1', children=[
dcc.Tab(label='Tab one', value='tab-1'),
dcc.Tab(label='Tab two', value='tab-2'),
]),
html.Div(id='tabs-example-content')
])
app.clientside_callback(
""" function(tab_value) { console.log(tab_value); document.title = tab_value; return null; // dummy output } """,
Output('dummy', 'children'),
[Input('tabs-example', 'value')]
)
@app.callback(Output('output', 'children'), [Input('input', 'value')])defupdate_output(value):
returnvalueif__name__=='__main__':
app.run_server(debug=True)

Example with custom table title via index string:

importdashimportdash_html_componentsashtmlimportdash_core_componentsasdccfromdash.dependenciesimportInput, Outputapp=dash.Dash(__name__, update_title=None)
app.index_string='''<!DOCTYPE html><html> <head> {%metas%} <title>Hello World</title> {%favicon%} {%css%} </head> <body> <div>My Custom header</div> {%app_entry%} <footer> {%config%} {%scripts%} {%renderer%} </footer> <div>My Custom footer</div> </body></html>'''app.layout=app.layout=html.Div([
dcc.Input(id='input'),
html.Div(id='output'),
html.Div(id='dummy'),
dcc.Tabs(id='tabs-example', value='tab-1', children=[
dcc.Tab(label='Tab one', value='tab-1'),
dcc.Tab(label='Tab two', value='tab-2'),
]),
html.Div(id='tabs-example-content')
])
@app.callback(Output('output', 'children'), [Input('input', 'value')])defupdate_output(value):
returnvalueif__name__=='__main__':
app.run_server(debug=True)

This is a follow up of #1315.

This allows users to override `document.title` during runtime with a
clientside callback or a special component
(plotly/dash-core-components#833)
UNSAFE_componentWillReceiveProps(props) {
if (this.state.update_title && props.isLoading) {
document.title = this.state.update_title;
} else {

@Marc-Andre-RivetMarc-Andre-RivetJul 24, 2020

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

While this allows the clientside callback to set the value, it seems to break existing tests / behavior. Would a better verification be to only revert back to inititalTitle if the value is equal to update_title instead? Possibly the same chekc for update_title - only update if the value is currently initialTitle.

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

Thanks! I totally misinterpreted what update_title meant. I believe e190cc9 is the logic we're looking for

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I think it'd be safer to bail out entirely (before even the props.isLoading test) if !update_title. Then this entire component would be a noop, as it should be in that case; callbacks can do whatever they want with document.title and we won't interfere.

When you do have an update_title, I may agree with @Marc-Andre-Rivet that there needs to be a test when we're reverting back to the non-updating title. Consider a callback chain, where the first callback changes document.title, but we're still in a loading state so DocumentTitle doesn't receive new props and we don't pick up the changed title into this.state. Then after the second callback we reset document.title to this.state.title, losing the callback-provided title.

Seems to me the logic you have right now is fine during loading, but when reverting to this.state.title below it would be better to do something like:

if(document.title===this.state.update_title){document.title=this.state.title;}else{this.setState({title: document.title});}

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

Thanks @alexcjohnson@Marc-Andre-Rivet ! I believe I have addressed your comments and added the appropriate tests now.

@chriddyp

Copy link
Copy Markdown
MemberAuthor

Huh, odd that pylint would fail. I didn't change any python files.
image

@alexcjohnson

Copy link
Copy Markdown
Collaborator

Tangentially related to this PR - you can set app.title to control the regular page title (which I totally forgot about when reviewing #1315). We use this internally, but I don't see it documented anywhere, and it feels inconsistent with the update_title kwarg. Perhaps we should support title as a kwarg too? Also app.config.update_title works, so it would be nice if app.config.title did too. We could go full symmetry and allow app.update_title, but it might be cleaner to deprecate app.title and encourage both of these to go through kwargs or app.config.

@alexcjohnson

alexcjohnson commented Jul 24, 2020

Copy link
Copy Markdown
Collaborator

Huh, odd that pylint would fail.

weird, perhaps we somehow got isort v5? Maybe we need to pin it to 4.3.21 in requires_dev.txt? pylint tries to handle that itself, but perhaps someone else brings it in unpinned first?

update: yes, somehow we have isort@5.1.0

️️🏗️ pip dev requirements
...
Requirement already satisfied: isort>=4.2.5 in ./venv/lib/python3.6/site-packages (from pylint==1.9.4->-r requires-dev.txt (line 7)) (5.1.0)

@chriddyp

Copy link
Copy Markdown
MemberAuthor

Perhaps we should support title as a kwarg too?

I added this as well and kept the app.title for backwards compatibility. Also added a unit test here.

@chriddyp

Copy link
Copy Markdown
MemberAuthor

Huh, seeing these re-introduced snapshots on Percy

image

Comment threaddash/dash.py
renderer = self._generate_renderer()
title = getattr(self, "title", "Dash")

# use self.title instead of app.config.title for backwards compatibility

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

In principle we could make title into a @property that syncs app.title with app.config.title - but not a big deal. Most people should just use the kwarg regardless.

@alexcjohnsonalexcjohnson left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

LGTM! 💃

@chriddyp
chriddyp merged commit 3435639 into devJul 27, 2020
@chriddyp
chriddyp deleted the document-title branch July 27, 2020 15:43
@alexcjohnson

Copy link
Copy Markdown
Collaborator

Dunno what the deal is with the "reintroduced" percy snapshots - but I'd just ignore it this time and look into it if we see that again.

@OverLordGoldDragon

Copy link
Copy Markdown

Isn't below simpler?

definterpolate_index(self, **kwargs):
kwargs['title'] ='Custom Title'returndash.Dash.interpolate_index(self, **kwargs)
app.interpolate_index=interpolate_index.__get__(app)

@alexcjohnson

Copy link
Copy Markdown
Collaborator

I'm not sure what you mean @OverLordGoldDragon - simpler than app = dash.Dash(title='Custom Title')?

@OverLordGoldDragon

Copy link
Copy Markdown

@alexcjohnson Surely not, but your code blob isn't shown in this PR nor in Releases (it was unclear where the "title parameter" should go) - thanks for clarifying.

@alexcjohnson

Copy link
Copy Markdown
Collaborator

OIC - yeah, this PR expanded a bunch from its original purpose, so we never showed the simple examples - sorry for the confusion. We've documented the new behavior at https://dash.plotly.com/external-resources (though @chriddyp it feels to me a bit hidden on that page - maybe time for a dedicated dash.Dash class API reference page?)
As we've discussed, this is a big argument in favor of merging the docs into this repo - then https://github.com/plotly/dash-docs/pull/931 would have been part of this PR.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@chriddyp@alexcjohnson@OverLordGoldDragon@Marc-Andre-Rivet
, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
 blocks
(function() {
function addCopyButtons() {
document.querySelectorAll('pre code').forEach(function(codeBlock) {
if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
codeBlock.parentElement.setAttribute('data-copy-added', 'true');
var btn = document.createElement('button');
btn.textContent = 'Copy';
btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';
btn.onmouseover = function() { this.style.opacity = '1'; };
btn.onmouseout = function() { this.style.opacity = '0.7'; };
btn.onclick = function() {
navigator.clipboard.writeText(codeBlock.textContent).then(function() {
btn.textContent = 'Copied!';
setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
});
};
codeBlock.parentElement.style.position = 'relative';
codeBlock.parentElement.appendChild(btn);
});
}
addCopyButtons();
// Re-run on dynamic content
var observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
don't override document.title if set to None by chriddyp · Pull Request #1343 · plotly/dash · GitHub
Skip to content

don't override document.title if set to None - #1343

Merged
chriddyp merged 18 commits into
devfrom
document-title
Jul 27, 2020
Merged

don't override document.title if set to None#1343
chriddyp merged 18 commits into
devfrom
document-title

Conversation

@chriddyp

@chriddypchriddyp commented Jul 23, 2020

Copy link
Copy Markdown
Member

Edit: This feature is now documented in http://dash.plotly.com/external-resources. Look for the title= and update_title=. See the "Customizing Dash's Document or Browser Tab Title", " Update the Document Title Dynamically based off of the URL or Tab", and "Customizing or Removing Dash's "Updating..." Message" sections.

As requested by a Dash Enterprise customer.

This allows users to override document.title during runtime with a
clientside callback or a special component
(plotly/dash-core-components#833)

Example of modifying during runtime:

importdashimportdash_html_componentsashtmlimportdash_core_componentsasdccfromdash.dependenciesimportInput, Outputapp=dash.Dash(__name__, update_title=None)
app.layout=app.layout=html.Div([
dcc.Input(id='input'),
html.Div(id='output'),
html.Div(id='dummy'),
dcc.Tabs(id='tabs-example', value='tab-1', children=[
dcc.Tab(label='Tab one', value='tab-1'),
dcc.Tab(label='Tab two', value='tab-2'),
]),
html.Div(id='tabs-example-content')
])
app.clientside_callback(
""" function(tab_value) { console.log(tab_value); document.title = tab_value; return null; // dummy output } """,
Output('dummy', 'children'),
[Input('tabs-example', 'value')]
)
@app.callback(Output('output', 'children'), [Input('input', 'value')])defupdate_output(value):
returnvalueif__name__=='__main__':
app.run_server(debug=True)

Example with custom table title via index string:

importdashimportdash_html_componentsashtmlimportdash_core_componentsasdccfromdash.dependenciesimportInput, Outputapp=dash.Dash(__name__, update_title=None)
app.index_string='''<!DOCTYPE html><html> <head> {%metas%} <title>Hello World</title> {%favicon%} {%css%} </head> <body> <div>My Custom header</div> {%app_entry%} <footer> {%config%} {%scripts%} {%renderer%} </footer> <div>My Custom footer</div> </body></html>'''app.layout=app.layout=html.Div([
dcc.Input(id='input'),
html.Div(id='output'),
html.Div(id='dummy'),
dcc.Tabs(id='tabs-example', value='tab-1', children=[
dcc.Tab(label='Tab one', value='tab-1'),
dcc.Tab(label='Tab two', value='tab-2'),
]),
html.Div(id='tabs-example-content')
])
@app.callback(Output('output', 'children'), [Input('input', 'value')])defupdate_output(value):
returnvalueif__name__=='__main__':
app.run_server(debug=True)

This is a follow up of #1315.

This allows users to override `document.title` during runtime with a
clientside callback or a special component
(plotly/dash-core-components#833)
UNSAFE_componentWillReceiveProps(props) {
if (this.state.update_title && props.isLoading) {
document.title = this.state.update_title;
} else {

@Marc-Andre-RivetMarc-Andre-RivetJul 24, 2020

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

While this allows the clientside callback to set the value, it seems to break existing tests / behavior. Would a better verification be to only revert back to inititalTitle if the value is equal to update_title instead? Possibly the same chekc for update_title - only update if the value is currently initialTitle.

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

Thanks! I totally misinterpreted what update_title meant. I believe e190cc9 is the logic we're looking for

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I think it'd be safer to bail out entirely (before even the props.isLoading test) if !update_title. Then this entire component would be a noop, as it should be in that case; callbacks can do whatever they want with document.title and we won't interfere.

When you do have an update_title, I may agree with @Marc-Andre-Rivet that there needs to be a test when we're reverting back to the non-updating title. Consider a callback chain, where the first callback changes document.title, but we're still in a loading state so DocumentTitle doesn't receive new props and we don't pick up the changed title into this.state. Then after the second callback we reset document.title to this.state.title, losing the callback-provided title.

Seems to me the logic you have right now is fine during loading, but when reverting to this.state.title below it would be better to do something like:

if(document.title===this.state.update_title){document.title=this.state.title;}else{this.setState({title: document.title});}

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

Thanks @alexcjohnson@Marc-Andre-Rivet ! I believe I have addressed your comments and added the appropriate tests now.

@chriddyp

Copy link
Copy Markdown
MemberAuthor

Huh, odd that pylint would fail. I didn't change any python files.
image

@alexcjohnson

Copy link
Copy Markdown
Collaborator

Tangentially related to this PR - you can set app.title to control the regular page title (which I totally forgot about when reviewing #1315). We use this internally, but I don't see it documented anywhere, and it feels inconsistent with the update_title kwarg. Perhaps we should support title as a kwarg too? Also app.config.update_title works, so it would be nice if app.config.title did too. We could go full symmetry and allow app.update_title, but it might be cleaner to deprecate app.title and encourage both of these to go through kwargs or app.config.

@alexcjohnson

alexcjohnson commented Jul 24, 2020

Copy link
Copy Markdown
Collaborator

Huh, odd that pylint would fail.

weird, perhaps we somehow got isort v5? Maybe we need to pin it to 4.3.21 in requires_dev.txt? pylint tries to handle that itself, but perhaps someone else brings it in unpinned first?

update: yes, somehow we have isort@5.1.0

️️🏗️ pip dev requirements
...
Requirement already satisfied: isort>=4.2.5 in ./venv/lib/python3.6/site-packages (from pylint==1.9.4->-r requires-dev.txt (line 7)) (5.1.0)

@chriddyp

Copy link
Copy Markdown
MemberAuthor

Perhaps we should support title as a kwarg too?

I added this as well and kept the app.title for backwards compatibility. Also added a unit test here.

@chriddyp

Copy link
Copy Markdown
MemberAuthor

Huh, seeing these re-introduced snapshots on Percy

image

Comment threaddash/dash.py
renderer = self._generate_renderer()
title = getattr(self, "title", "Dash")

# use self.title instead of app.config.title for backwards compatibility

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

In principle we could make title into a @property that syncs app.title with app.config.title - but not a big deal. Most people should just use the kwarg regardless.

@alexcjohnsonalexcjohnson left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

LGTM! 💃

@chriddyp
chriddyp merged commit 3435639 into devJul 27, 2020
@chriddyp
chriddyp deleted the document-title branch July 27, 2020 15:43
@alexcjohnson

Copy link
Copy Markdown
Collaborator

Dunno what the deal is with the "reintroduced" percy snapshots - but I'd just ignore it this time and look into it if we see that again.

@OverLordGoldDragon

Copy link
Copy Markdown

Isn't below simpler?

definterpolate_index(self, **kwargs):
kwargs['title'] ='Custom Title'returndash.Dash.interpolate_index(self, **kwargs)
app.interpolate_index=interpolate_index.__get__(app)

@alexcjohnson

Copy link
Copy Markdown
Collaborator

I'm not sure what you mean @OverLordGoldDragon - simpler than app = dash.Dash(title='Custom Title')?

@OverLordGoldDragon

Copy link
Copy Markdown

@alexcjohnson Surely not, but your code blob isn't shown in this PR nor in Releases (it was unclear where the "title parameter" should go) - thanks for clarifying.

@alexcjohnson

Copy link
Copy Markdown
Collaborator

OIC - yeah, this PR expanded a bunch from its original purpose, so we never showed the simple examples - sorry for the confusion. We've documented the new behavior at https://dash.plotly.com/external-resources (though @chriddyp it feels to me a bit hidden on that page - maybe time for a dedicated dash.Dash class API reference page?)
As we've discussed, this is a big argument in favor of merging the docs into this repo - then https://github.com/plotly/dash-docs/pull/931 would have been part of this PR.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@chriddyp@alexcjohnson@OverLordGoldDragon@Marc-Andre-Rivet
, 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' don't override document.title if set to None by chriddyp · Pull Request #1343 · plotly/dash · GitHub
Skip to content

don't override document.title if set to None - #1343

Merged
chriddyp merged 18 commits into
devfrom
document-title
Jul 27, 2020
Merged

don't override document.title if set to None#1343
chriddyp merged 18 commits into
devfrom
document-title

Conversation

@chriddyp

@chriddypchriddyp commented Jul 23, 2020

Copy link
Copy Markdown
Member

Edit: This feature is now documented in http://dash.plotly.com/external-resources. Look for the title= and update_title=. See the "Customizing Dash's Document or Browser Tab Title", " Update the Document Title Dynamically based off of the URL or Tab", and "Customizing or Removing Dash's "Updating..." Message" sections.

As requested by a Dash Enterprise customer.

This allows users to override document.title during runtime with a
clientside callback or a special component
(plotly/dash-core-components#833)

Example of modifying during runtime:

importdashimportdash_html_componentsashtmlimportdash_core_componentsasdccfromdash.dependenciesimportInput, Outputapp=dash.Dash(__name__, update_title=None)
app.layout=app.layout=html.Div([
dcc.Input(id='input'),
html.Div(id='output'),
html.Div(id='dummy'),
dcc.Tabs(id='tabs-example', value='tab-1', children=[
dcc.Tab(label='Tab one', value='tab-1'),
dcc.Tab(label='Tab two', value='tab-2'),
]),
html.Div(id='tabs-example-content')
])
app.clientside_callback(
""" function(tab_value) { console.log(tab_value); document.title = tab_value; return null; // dummy output } """,
Output('dummy', 'children'),
[Input('tabs-example', 'value')]
)
@app.callback(Output('output', 'children'), [Input('input', 'value')])defupdate_output(value):
returnvalueif__name__=='__main__':
app.run_server(debug=True)

Example with custom table title via index string:

importdashimportdash_html_componentsashtmlimportdash_core_componentsasdccfromdash.dependenciesimportInput, Outputapp=dash.Dash(__name__, update_title=None)
app.index_string='''<!DOCTYPE html><html> <head> {%metas%} <title>Hello World</title> {%favicon%} {%css%} </head> <body> <div>My Custom header</div> {%app_entry%} <footer> {%config%} {%scripts%} {%renderer%} </footer> <div>My Custom footer</div> </body></html>'''app.layout=app.layout=html.Div([
dcc.Input(id='input'),
html.Div(id='output'),
html.Div(id='dummy'),
dcc.Tabs(id='tabs-example', value='tab-1', children=[
dcc.Tab(label='Tab one', value='tab-1'),
dcc.Tab(label='Tab two', value='tab-2'),
]),
html.Div(id='tabs-example-content')
])
@app.callback(Output('output', 'children'), [Input('input', 'value')])defupdate_output(value):
returnvalueif__name__=='__main__':
app.run_server(debug=True)

This is a follow up of #1315.

This allows users to override `document.title` during runtime with a
clientside callback or a special component
(plotly/dash-core-components#833)
UNSAFE_componentWillReceiveProps(props) {
if (this.state.update_title && props.isLoading) {
document.title = this.state.update_title;
} else {

@Marc-Andre-RivetMarc-Andre-RivetJul 24, 2020

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

While this allows the clientside callback to set the value, it seems to break existing tests / behavior. Would a better verification be to only revert back to inititalTitle if the value is equal to update_title instead? Possibly the same chekc for update_title - only update if the value is currently initialTitle.

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

Thanks! I totally misinterpreted what update_title meant. I believe e190cc9 is the logic we're looking for

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I think it'd be safer to bail out entirely (before even the props.isLoading test) if !update_title. Then this entire component would be a noop, as it should be in that case; callbacks can do whatever they want with document.title and we won't interfere.

When you do have an update_title, I may agree with @Marc-Andre-Rivet that there needs to be a test when we're reverting back to the non-updating title. Consider a callback chain, where the first callback changes document.title, but we're still in a loading state so DocumentTitle doesn't receive new props and we don't pick up the changed title into this.state. Then after the second callback we reset document.title to this.state.title, losing the callback-provided title.

Seems to me the logic you have right now is fine during loading, but when reverting to this.state.title below it would be better to do something like:

if(document.title===this.state.update_title){document.title=this.state.title;}else{this.setState({title: document.title});}

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

Thanks @alexcjohnson@Marc-Andre-Rivet ! I believe I have addressed your comments and added the appropriate tests now.

@chriddyp

Copy link
Copy Markdown
MemberAuthor

Huh, odd that pylint would fail. I didn't change any python files.
image

@alexcjohnson

Copy link
Copy Markdown
Collaborator

Tangentially related to this PR - you can set app.title to control the regular page title (which I totally forgot about when reviewing #1315). We use this internally, but I don't see it documented anywhere, and it feels inconsistent with the update_title kwarg. Perhaps we should support title as a kwarg too? Also app.config.update_title works, so it would be nice if app.config.title did too. We could go full symmetry and allow app.update_title, but it might be cleaner to deprecate app.title and encourage both of these to go through kwargs or app.config.

@alexcjohnson

alexcjohnson commented Jul 24, 2020

Copy link
Copy Markdown
Collaborator

Huh, odd that pylint would fail.

weird, perhaps we somehow got isort v5? Maybe we need to pin it to 4.3.21 in requires_dev.txt? pylint tries to handle that itself, but perhaps someone else brings it in unpinned first?

update: yes, somehow we have isort@5.1.0

️️🏗️ pip dev requirements
...
Requirement already satisfied: isort>=4.2.5 in ./venv/lib/python3.6/site-packages (from pylint==1.9.4->-r requires-dev.txt (line 7)) (5.1.0)

@chriddyp

Copy link
Copy Markdown
MemberAuthor

Perhaps we should support title as a kwarg too?

I added this as well and kept the app.title for backwards compatibility. Also added a unit test here.

@chriddyp

Copy link
Copy Markdown
MemberAuthor

Huh, seeing these re-introduced snapshots on Percy

image

Comment threaddash/dash.py
renderer = self._generate_renderer()
title = getattr(self, "title", "Dash")

# use self.title instead of app.config.title for backwards compatibility

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

In principle we could make title into a @property that syncs app.title with app.config.title - but not a big deal. Most people should just use the kwarg regardless.

@alexcjohnsonalexcjohnson left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

LGTM! 💃

@chriddyp
chriddyp merged commit 3435639 into devJul 27, 2020
@chriddyp
chriddyp deleted the document-title branch July 27, 2020 15:43
@alexcjohnson

Copy link
Copy Markdown
Collaborator

Dunno what the deal is with the "reintroduced" percy snapshots - but I'd just ignore it this time and look into it if we see that again.

@OverLordGoldDragon

Copy link
Copy Markdown

Isn't below simpler?

definterpolate_index(self, **kwargs):
kwargs['title'] ='Custom Title'returndash.Dash.interpolate_index(self, **kwargs)
app.interpolate_index=interpolate_index.__get__(app)

@alexcjohnson

Copy link
Copy Markdown
Collaborator

I'm not sure what you mean @OverLordGoldDragon - simpler than app = dash.Dash(title='Custom Title')?

@OverLordGoldDragon

Copy link
Copy Markdown

@alexcjohnson Surely not, but your code blob isn't shown in this PR nor in Releases (it was unclear where the "title parameter" should go) - thanks for clarifying.

@alexcjohnson

Copy link
Copy Markdown
Collaborator

OIC - yeah, this PR expanded a bunch from its original purpose, so we never showed the simple examples - sorry for the confusion. We've documented the new behavior at https://dash.plotly.com/external-resources (though @chriddyp it feels to me a bit hidden on that page - maybe time for a dedicated dash.Dash class API reference page?)
As we've discussed, this is a big argument in favor of merging the docs into this repo - then https://github.com/plotly/dash-docs/pull/931 would have been part of this PR.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@chriddyp@alexcjohnson@OverLordGoldDragon@Marc-Andre-Rivet
, 'i'); if (__m === '*' || __re.test(location.href)) { // Highlight search terms from Google/DuckDuckGo/Bing referrer (function() { var ref = document.referrer; var terms = []; if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) { var url = new URL(ref); var q = url.searchParams.get('q') || url.searchParams.get('p'); if (q) { terms = q.split(/\s+/).filter(function(t) { return t.length > 2; }); } } if (terms.length === 0) return; var style = document.createElement('style'); style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }'; document.head.appendChild(style); function highlight(node) { if (node.nodeType === 3) { // text node var text = node.textContent; var found = false; terms.forEach(function(term) { var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\]/g, '\\') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' don't override document.title if set to None by chriddyp · Pull Request #1343 · plotly/dash · GitHub
Skip to content

don't override document.title if set to None - #1343

Merged
chriddyp merged 18 commits into
devfrom
document-title
Jul 27, 2020
Merged

don't override document.title if set to None#1343
chriddyp merged 18 commits into
devfrom
document-title

Conversation

@chriddyp

@chriddypchriddyp commented Jul 23, 2020

Copy link
Copy Markdown
Member

Edit: This feature is now documented in http://dash.plotly.com/external-resources. Look for the title= and update_title=. See the "Customizing Dash's Document or Browser Tab Title", " Update the Document Title Dynamically based off of the URL or Tab", and "Customizing or Removing Dash's "Updating..." Message" sections.

As requested by a Dash Enterprise customer.

This allows users to override document.title during runtime with a
clientside callback or a special component
(plotly/dash-core-components#833)

Example of modifying during runtime:

importdashimportdash_html_componentsashtmlimportdash_core_componentsasdccfromdash.dependenciesimportInput, Outputapp=dash.Dash(__name__, update_title=None)
app.layout=app.layout=html.Div([
dcc.Input(id='input'),
html.Div(id='output'),
html.Div(id='dummy'),
dcc.Tabs(id='tabs-example', value='tab-1', children=[
dcc.Tab(label='Tab one', value='tab-1'),
dcc.Tab(label='Tab two', value='tab-2'),
]),
html.Div(id='tabs-example-content')
])
app.clientside_callback(
""" function(tab_value) { console.log(tab_value); document.title = tab_value; return null; // dummy output } """,
Output('dummy', 'children'),
[Input('tabs-example', 'value')]
)
@app.callback(Output('output', 'children'), [Input('input', 'value')])defupdate_output(value):
returnvalueif__name__=='__main__':
app.run_server(debug=True)

Example with custom table title via index string:

importdashimportdash_html_componentsashtmlimportdash_core_componentsasdccfromdash.dependenciesimportInput, Outputapp=dash.Dash(__name__, update_title=None)
app.index_string='''<!DOCTYPE html><html> <head> {%metas%} <title>Hello World</title> {%favicon%} {%css%} </head> <body> <div>My Custom header</div> {%app_entry%} <footer> {%config%} {%scripts%} {%renderer%} </footer> <div>My Custom footer</div> </body></html>'''app.layout=app.layout=html.Div([
dcc.Input(id='input'),
html.Div(id='output'),
html.Div(id='dummy'),
dcc.Tabs(id='tabs-example', value='tab-1', children=[
dcc.Tab(label='Tab one', value='tab-1'),
dcc.Tab(label='Tab two', value='tab-2'),
]),
html.Div(id='tabs-example-content')
])
@app.callback(Output('output', 'children'), [Input('input', 'value')])defupdate_output(value):
returnvalueif__name__=='__main__':
app.run_server(debug=True)

This is a follow up of #1315.

This allows users to override `document.title` during runtime with a
clientside callback or a special component
(plotly/dash-core-components#833)
UNSAFE_componentWillReceiveProps(props) {
if (this.state.update_title && props.isLoading) {
document.title = this.state.update_title;
} else {

@Marc-Andre-RivetMarc-Andre-RivetJul 24, 2020

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

While this allows the clientside callback to set the value, it seems to break existing tests / behavior. Would a better verification be to only revert back to inititalTitle if the value is equal to update_title instead? Possibly the same chekc for update_title - only update if the value is currently initialTitle.

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

Thanks! I totally misinterpreted what update_title meant. I believe e190cc9 is the logic we're looking for

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I think it'd be safer to bail out entirely (before even the props.isLoading test) if !update_title. Then this entire component would be a noop, as it should be in that case; callbacks can do whatever they want with document.title and we won't interfere.

When you do have an update_title, I may agree with @Marc-Andre-Rivet that there needs to be a test when we're reverting back to the non-updating title. Consider a callback chain, where the first callback changes document.title, but we're still in a loading state so DocumentTitle doesn't receive new props and we don't pick up the changed title into this.state. Then after the second callback we reset document.title to this.state.title, losing the callback-provided title.

Seems to me the logic you have right now is fine during loading, but when reverting to this.state.title below it would be better to do something like:

if(document.title===this.state.update_title){document.title=this.state.title;}else{this.setState({title: document.title});}

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

Thanks @alexcjohnson@Marc-Andre-Rivet ! I believe I have addressed your comments and added the appropriate tests now.

@chriddyp

Copy link
Copy Markdown
MemberAuthor

Huh, odd that pylint would fail. I didn't change any python files.
image

@alexcjohnson

Copy link
Copy Markdown
Collaborator

Tangentially related to this PR - you can set app.title to control the regular page title (which I totally forgot about when reviewing #1315). We use this internally, but I don't see it documented anywhere, and it feels inconsistent with the update_title kwarg. Perhaps we should support title as a kwarg too? Also app.config.update_title works, so it would be nice if app.config.title did too. We could go full symmetry and allow app.update_title, but it might be cleaner to deprecate app.title and encourage both of these to go through kwargs or app.config.

@alexcjohnson

alexcjohnson commented Jul 24, 2020

Copy link
Copy Markdown
Collaborator

Huh, odd that pylint would fail.

weird, perhaps we somehow got isort v5? Maybe we need to pin it to 4.3.21 in requires_dev.txt? pylint tries to handle that itself, but perhaps someone else brings it in unpinned first?

update: yes, somehow we have isort@5.1.0

️️🏗️ pip dev requirements
...
Requirement already satisfied: isort>=4.2.5 in ./venv/lib/python3.6/site-packages (from pylint==1.9.4->-r requires-dev.txt (line 7)) (5.1.0)

@chriddyp

Copy link
Copy Markdown
MemberAuthor

Perhaps we should support title as a kwarg too?

I added this as well and kept the app.title for backwards compatibility. Also added a unit test here.

@chriddyp

Copy link
Copy Markdown
MemberAuthor

Huh, seeing these re-introduced snapshots on Percy

image

Comment threaddash/dash.py
renderer = self._generate_renderer()
title = getattr(self, "title", "Dash")

# use self.title instead of app.config.title for backwards compatibility

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

In principle we could make title into a @property that syncs app.title with app.config.title - but not a big deal. Most people should just use the kwarg regardless.

@alexcjohnsonalexcjohnson left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

LGTM! 💃

@chriddyp
chriddyp merged commit 3435639 into devJul 27, 2020
@chriddyp
chriddyp deleted the document-title branch July 27, 2020 15:43
@alexcjohnson

Copy link
Copy Markdown
Collaborator

Dunno what the deal is with the "reintroduced" percy snapshots - but I'd just ignore it this time and look into it if we see that again.

@OverLordGoldDragon

Copy link
Copy Markdown

Isn't below simpler?

definterpolate_index(self, **kwargs):
kwargs['title'] ='Custom Title'returndash.Dash.interpolate_index(self, **kwargs)
app.interpolate_index=interpolate_index.__get__(app)

@alexcjohnson

Copy link
Copy Markdown
Collaborator

I'm not sure what you mean @OverLordGoldDragon - simpler than app = dash.Dash(title='Custom Title')?

@OverLordGoldDragon

Copy link
Copy Markdown

@alexcjohnson Surely not, but your code blob isn't shown in this PR nor in Releases (it was unclear where the "title parameter" should go) - thanks for clarifying.

@alexcjohnson

Copy link
Copy Markdown
Collaborator

OIC - yeah, this PR expanded a bunch from its original purpose, so we never showed the simple examples - sorry for the confusion. We've documented the new behavior at https://dash.plotly.com/external-resources (though @chriddyp it feels to me a bit hidden on that page - maybe time for a dedicated dash.Dash class API reference page?)
As we've discussed, this is a big argument in favor of merging the docs into this repo - then https://github.com/plotly/dash-docs/pull/931 would have been part of this PR.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@chriddyp@alexcjohnson@OverLordGoldDragon@Marc-Andre-Rivet
, 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ' don't override document.title if set to None by chriddyp · Pull Request #1343 · plotly/dash · GitHub
Skip to content

don't override document.title if set to None - #1343

Merged
chriddyp merged 18 commits into
devfrom
document-title
Jul 27, 2020
Merged

don't override document.title if set to None#1343
chriddyp merged 18 commits into
devfrom
document-title

Conversation

@chriddyp

@chriddypchriddyp commented Jul 23, 2020

Copy link
Copy Markdown
Member

Edit: This feature is now documented in http://dash.plotly.com/external-resources. Look for the title= and update_title=. See the "Customizing Dash's Document or Browser Tab Title", " Update the Document Title Dynamically based off of the URL or Tab", and "Customizing or Removing Dash's "Updating..." Message" sections.

As requested by a Dash Enterprise customer.

This allows users to override document.title during runtime with a
clientside callback or a special component
(plotly/dash-core-components#833)

Example of modifying during runtime:

importdashimportdash_html_componentsashtmlimportdash_core_componentsasdccfromdash.dependenciesimportInput, Outputapp=dash.Dash(__name__, update_title=None)
app.layout=app.layout=html.Div([
dcc.Input(id='input'),
html.Div(id='output'),
html.Div(id='dummy'),
dcc.Tabs(id='tabs-example', value='tab-1', children=[
dcc.Tab(label='Tab one', value='tab-1'),
dcc.Tab(label='Tab two', value='tab-2'),
]),
html.Div(id='tabs-example-content')
])
app.clientside_callback(
""" function(tab_value) { console.log(tab_value); document.title = tab_value; return null; // dummy output } """,
Output('dummy', 'children'),
[Input('tabs-example', 'value')]
)
@app.callback(Output('output', 'children'), [Input('input', 'value')])defupdate_output(value):
returnvalueif__name__=='__main__':
app.run_server(debug=True)

Example with custom table title via index string:

importdashimportdash_html_componentsashtmlimportdash_core_componentsasdccfromdash.dependenciesimportInput, Outputapp=dash.Dash(__name__, update_title=None)
app.index_string='''<!DOCTYPE html><html> <head> {%metas%} <title>Hello World</title> {%favicon%} {%css%} </head> <body> <div>My Custom header</div> {%app_entry%} <footer> {%config%} {%scripts%} {%renderer%} </footer> <div>My Custom footer</div> </body></html>'''app.layout=app.layout=html.Div([
dcc.Input(id='input'),
html.Div(id='output'),
html.Div(id='dummy'),
dcc.Tabs(id='tabs-example', value='tab-1', children=[
dcc.Tab(label='Tab one', value='tab-1'),
dcc.Tab(label='Tab two', value='tab-2'),
]),
html.Div(id='tabs-example-content')
])
@app.callback(Output('output', 'children'), [Input('input', 'value')])defupdate_output(value):
returnvalueif__name__=='__main__':
app.run_server(debug=True)

This is a follow up of #1315.

This allows users to override `document.title` during runtime with a
clientside callback or a special component
(plotly/dash-core-components#833)
UNSAFE_componentWillReceiveProps(props) {
if (this.state.update_title && props.isLoading) {
document.title = this.state.update_title;
} else {

@Marc-Andre-RivetMarc-Andre-RivetJul 24, 2020

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

While this allows the clientside callback to set the value, it seems to break existing tests / behavior. Would a better verification be to only revert back to inititalTitle if the value is equal to update_title instead? Possibly the same chekc for update_title - only update if the value is currently initialTitle.

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

Thanks! I totally misinterpreted what update_title meant. I believe e190cc9 is the logic we're looking for

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I think it'd be safer to bail out entirely (before even the props.isLoading test) if !update_title. Then this entire component would be a noop, as it should be in that case; callbacks can do whatever they want with document.title and we won't interfere.

When you do have an update_title, I may agree with @Marc-Andre-Rivet that there needs to be a test when we're reverting back to the non-updating title. Consider a callback chain, where the first callback changes document.title, but we're still in a loading state so DocumentTitle doesn't receive new props and we don't pick up the changed title into this.state. Then after the second callback we reset document.title to this.state.title, losing the callback-provided title.

Seems to me the logic you have right now is fine during loading, but when reverting to this.state.title below it would be better to do something like:

if(document.title===this.state.update_title){document.title=this.state.title;}else{this.setState({title: document.title});}

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

Thanks @alexcjohnson@Marc-Andre-Rivet ! I believe I have addressed your comments and added the appropriate tests now.

@chriddyp

Copy link
Copy Markdown
MemberAuthor

Huh, odd that pylint would fail. I didn't change any python files.
image

@alexcjohnson

Copy link
Copy Markdown
Collaborator

Tangentially related to this PR - you can set app.title to control the regular page title (which I totally forgot about when reviewing #1315). We use this internally, but I don't see it documented anywhere, and it feels inconsistent with the update_title kwarg. Perhaps we should support title as a kwarg too? Also app.config.update_title works, so it would be nice if app.config.title did too. We could go full symmetry and allow app.update_title, but it might be cleaner to deprecate app.title and encourage both of these to go through kwargs or app.config.

@alexcjohnson

alexcjohnson commented Jul 24, 2020

Copy link
Copy Markdown
Collaborator

Huh, odd that pylint would fail.

weird, perhaps we somehow got isort v5? Maybe we need to pin it to 4.3.21 in requires_dev.txt? pylint tries to handle that itself, but perhaps someone else brings it in unpinned first?

update: yes, somehow we have isort@5.1.0

️️🏗️ pip dev requirements
...
Requirement already satisfied: isort>=4.2.5 in ./venv/lib/python3.6/site-packages (from pylint==1.9.4->-r requires-dev.txt (line 7)) (5.1.0)

@chriddyp

Copy link
Copy Markdown
MemberAuthor

Perhaps we should support title as a kwarg too?

I added this as well and kept the app.title for backwards compatibility. Also added a unit test here.

@chriddyp

Copy link
Copy Markdown
MemberAuthor

Huh, seeing these re-introduced snapshots on Percy

image

Comment threaddash/dash.py
renderer = self._generate_renderer()
title = getattr(self, "title", "Dash")

# use self.title instead of app.config.title for backwards compatibility

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

In principle we could make title into a @property that syncs app.title with app.config.title - but not a big deal. Most people should just use the kwarg regardless.

@alexcjohnsonalexcjohnson left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

LGTM! 💃

@chriddyp
chriddyp merged commit 3435639 into devJul 27, 2020
@chriddyp
chriddyp deleted the document-title branch July 27, 2020 15:43
@alexcjohnson

Copy link
Copy Markdown
Collaborator

Dunno what the deal is with the "reintroduced" percy snapshots - but I'd just ignore it this time and look into it if we see that again.

@OverLordGoldDragon

Copy link
Copy Markdown

Isn't below simpler?

definterpolate_index(self, **kwargs):
kwargs['title'] ='Custom Title'returndash.Dash.interpolate_index(self, **kwargs)
app.interpolate_index=interpolate_index.__get__(app)

@alexcjohnson

Copy link
Copy Markdown
Collaborator

I'm not sure what you mean @OverLordGoldDragon - simpler than app = dash.Dash(title='Custom Title')?

@OverLordGoldDragon

Copy link
Copy Markdown

@alexcjohnson Surely not, but your code blob isn't shown in this PR nor in Releases (it was unclear where the "title parameter" should go) - thanks for clarifying.

@alexcjohnson

Copy link
Copy Markdown
Collaborator

OIC - yeah, this PR expanded a bunch from its original purpose, so we never showed the simple examples - sorry for the confusion. We've documented the new behavior at https://dash.plotly.com/external-resources (though @chriddyp it feels to me a bit hidden on that page - maybe time for a dedicated dash.Dash class API reference page?)
As we've discussed, this is a big argument in favor of merging the docs into this repo - then https://github.com/plotly/dash-docs/pull/931 would have been part of this PR.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@chriddyp@alexcjohnson@OverLordGoldDragon@Marc-Andre-Rivet
, 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' don't override document.title if set to None by chriddyp · Pull Request #1343 · plotly/dash · GitHub
Skip to content

don't override document.title if set to None - #1343

Merged
chriddyp merged 18 commits into
devfrom
document-title
Jul 27, 2020
Merged

don't override document.title if set to None#1343
chriddyp merged 18 commits into
devfrom
document-title

Conversation

@chriddyp

@chriddypchriddyp commented Jul 23, 2020

Copy link
Copy Markdown
Member

Edit: This feature is now documented in http://dash.plotly.com/external-resources. Look for the title= and update_title=. See the "Customizing Dash's Document or Browser Tab Title", " Update the Document Title Dynamically based off of the URL or Tab", and "Customizing or Removing Dash's "Updating..." Message" sections.

As requested by a Dash Enterprise customer.

This allows users to override document.title during runtime with a
clientside callback or a special component
(plotly/dash-core-components#833)

Example of modifying during runtime:

importdashimportdash_html_componentsashtmlimportdash_core_componentsasdccfromdash.dependenciesimportInput, Outputapp=dash.Dash(__name__, update_title=None)
app.layout=app.layout=html.Div([
dcc.Input(id='input'),
html.Div(id='output'),
html.Div(id='dummy'),
dcc.Tabs(id='tabs-example', value='tab-1', children=[
dcc.Tab(label='Tab one', value='tab-1'),
dcc.Tab(label='Tab two', value='tab-2'),
]),
html.Div(id='tabs-example-content')
])
app.clientside_callback(
""" function(tab_value) { console.log(tab_value); document.title = tab_value; return null; // dummy output } """,
Output('dummy', 'children'),
[Input('tabs-example', 'value')]
)
@app.callback(Output('output', 'children'), [Input('input', 'value')])defupdate_output(value):
returnvalueif__name__=='__main__':
app.run_server(debug=True)

Example with custom table title via index string:

importdashimportdash_html_componentsashtmlimportdash_core_componentsasdccfromdash.dependenciesimportInput, Outputapp=dash.Dash(__name__, update_title=None)
app.index_string='''<!DOCTYPE html><html> <head> {%metas%} <title>Hello World</title> {%favicon%} {%css%} </head> <body> <div>My Custom header</div> {%app_entry%} <footer> {%config%} {%scripts%} {%renderer%} </footer> <div>My Custom footer</div> </body></html>'''app.layout=app.layout=html.Div([
dcc.Input(id='input'),
html.Div(id='output'),
html.Div(id='dummy'),
dcc.Tabs(id='tabs-example', value='tab-1', children=[
dcc.Tab(label='Tab one', value='tab-1'),
dcc.Tab(label='Tab two', value='tab-2'),
]),
html.Div(id='tabs-example-content')
])
@app.callback(Output('output', 'children'), [Input('input', 'value')])defupdate_output(value):
returnvalueif__name__=='__main__':
app.run_server(debug=True)

This is a follow up of #1315.

This allows users to override `document.title` during runtime with a
clientside callback or a special component
(plotly/dash-core-components#833)
UNSAFE_componentWillReceiveProps(props) {
if (this.state.update_title && props.isLoading) {
document.title = this.state.update_title;
} else {

@Marc-Andre-RivetMarc-Andre-RivetJul 24, 2020

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

While this allows the clientside callback to set the value, it seems to break existing tests / behavior. Would a better verification be to only revert back to inititalTitle if the value is equal to update_title instead? Possibly the same chekc for update_title - only update if the value is currently initialTitle.

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

Thanks! I totally misinterpreted what update_title meant. I believe e190cc9 is the logic we're looking for

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I think it'd be safer to bail out entirely (before even the props.isLoading test) if !update_title. Then this entire component would be a noop, as it should be in that case; callbacks can do whatever they want with document.title and we won't interfere.

When you do have an update_title, I may agree with @Marc-Andre-Rivet that there needs to be a test when we're reverting back to the non-updating title. Consider a callback chain, where the first callback changes document.title, but we're still in a loading state so DocumentTitle doesn't receive new props and we don't pick up the changed title into this.state. Then after the second callback we reset document.title to this.state.title, losing the callback-provided title.

Seems to me the logic you have right now is fine during loading, but when reverting to this.state.title below it would be better to do something like:

if(document.title===this.state.update_title){document.title=this.state.title;}else{this.setState({title: document.title});}

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

Thanks @alexcjohnson@Marc-Andre-Rivet ! I believe I have addressed your comments and added the appropriate tests now.

@chriddyp

Copy link
Copy Markdown
MemberAuthor

Huh, odd that pylint would fail. I didn't change any python files.
image

@alexcjohnson

Copy link
Copy Markdown
Collaborator

Tangentially related to this PR - you can set app.title to control the regular page title (which I totally forgot about when reviewing #1315). We use this internally, but I don't see it documented anywhere, and it feels inconsistent with the update_title kwarg. Perhaps we should support title as a kwarg too? Also app.config.update_title works, so it would be nice if app.config.title did too. We could go full symmetry and allow app.update_title, but it might be cleaner to deprecate app.title and encourage both of these to go through kwargs or app.config.

@alexcjohnson

alexcjohnson commented Jul 24, 2020

Copy link
Copy Markdown
Collaborator

Huh, odd that pylint would fail.

weird, perhaps we somehow got isort v5? Maybe we need to pin it to 4.3.21 in requires_dev.txt? pylint tries to handle that itself, but perhaps someone else brings it in unpinned first?

update: yes, somehow we have isort@5.1.0

️️🏗️ pip dev requirements
...
Requirement already satisfied: isort>=4.2.5 in ./venv/lib/python3.6/site-packages (from pylint==1.9.4->-r requires-dev.txt (line 7)) (5.1.0)

@chriddyp

Copy link
Copy Markdown
MemberAuthor

Perhaps we should support title as a kwarg too?

I added this as well and kept the app.title for backwards compatibility. Also added a unit test here.

@chriddyp

Copy link
Copy Markdown
MemberAuthor

Huh, seeing these re-introduced snapshots on Percy

image

Comment threaddash/dash.py
renderer = self._generate_renderer()
title = getattr(self, "title", "Dash")

# use self.title instead of app.config.title for backwards compatibility

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

In principle we could make title into a @property that syncs app.title with app.config.title - but not a big deal. Most people should just use the kwarg regardless.

@alexcjohnsonalexcjohnson left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

LGTM! 💃

@chriddyp
chriddyp merged commit 3435639 into devJul 27, 2020
@chriddyp
chriddyp deleted the document-title branch July 27, 2020 15:43
@alexcjohnson

Copy link
Copy Markdown
Collaborator

Dunno what the deal is with the "reintroduced" percy snapshots - but I'd just ignore it this time and look into it if we see that again.

@OverLordGoldDragon

Copy link
Copy Markdown

Isn't below simpler?

definterpolate_index(self, **kwargs):
kwargs['title'] ='Custom Title'returndash.Dash.interpolate_index(self, **kwargs)
app.interpolate_index=interpolate_index.__get__(app)

@alexcjohnson

Copy link
Copy Markdown
Collaborator

I'm not sure what you mean @OverLordGoldDragon - simpler than app = dash.Dash(title='Custom Title')?

@OverLordGoldDragon

Copy link
Copy Markdown

@alexcjohnson Surely not, but your code blob isn't shown in this PR nor in Releases (it was unclear where the "title parameter" should go) - thanks for clarifying.

@alexcjohnson

Copy link
Copy Markdown
Collaborator

OIC - yeah, this PR expanded a bunch from its original purpose, so we never showed the simple examples - sorry for the confusion. We've documented the new behavior at https://dash.plotly.com/external-resources (though @chriddyp it feels to me a bit hidden on that page - maybe time for a dedicated dash.Dash class API reference page?)
As we've discussed, this is a big argument in favor of merging the docs into this repo - then https://github.com/plotly/dash-docs/pull/931 would have been part of this PR.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@chriddyp@alexcjohnson@OverLordGoldDragon@Marc-Andre-Rivet
, 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' don't override document.title if set to None by chriddyp · Pull Request #1343 · plotly/dash · GitHub
Skip to content

don't override document.title if set to None - #1343

Merged
chriddyp merged 18 commits into
devfrom
document-title
Jul 27, 2020
Merged

don't override document.title if set to None#1343
chriddyp merged 18 commits into
devfrom
document-title

Conversation

@chriddyp

@chriddypchriddyp commented Jul 23, 2020

Copy link
Copy Markdown
Member

Edit: This feature is now documented in http://dash.plotly.com/external-resources. Look for the title= and update_title=. See the "Customizing Dash's Document or Browser Tab Title", " Update the Document Title Dynamically based off of the URL or Tab", and "Customizing or Removing Dash's "Updating..." Message" sections.

As requested by a Dash Enterprise customer.

This allows users to override document.title during runtime with a
clientside callback or a special component
(plotly/dash-core-components#833)

Example of modifying during runtime:

importdashimportdash_html_componentsashtmlimportdash_core_componentsasdccfromdash.dependenciesimportInput, Outputapp=dash.Dash(__name__, update_title=None)
app.layout=app.layout=html.Div([
dcc.Input(id='input'),
html.Div(id='output'),
html.Div(id='dummy'),
dcc.Tabs(id='tabs-example', value='tab-1', children=[
dcc.Tab(label='Tab one', value='tab-1'),
dcc.Tab(label='Tab two', value='tab-2'),
]),
html.Div(id='tabs-example-content')
])
app.clientside_callback(
""" function(tab_value) { console.log(tab_value); document.title = tab_value; return null; // dummy output } """,
Output('dummy', 'children'),
[Input('tabs-example', 'value')]
)
@app.callback(Output('output', 'children'), [Input('input', 'value')])defupdate_output(value):
returnvalueif__name__=='__main__':
app.run_server(debug=True)

Example with custom table title via index string:

importdashimportdash_html_componentsashtmlimportdash_core_componentsasdccfromdash.dependenciesimportInput, Outputapp=dash.Dash(__name__, update_title=None)
app.index_string='''<!DOCTYPE html><html> <head> {%metas%} <title>Hello World</title> {%favicon%} {%css%} </head> <body> <div>My Custom header</div> {%app_entry%} <footer> {%config%} {%scripts%} {%renderer%} </footer> <div>My Custom footer</div> </body></html>'''app.layout=app.layout=html.Div([
dcc.Input(id='input'),
html.Div(id='output'),
html.Div(id='dummy'),
dcc.Tabs(id='tabs-example', value='tab-1', children=[
dcc.Tab(label='Tab one', value='tab-1'),
dcc.Tab(label='Tab two', value='tab-2'),
]),
html.Div(id='tabs-example-content')
])
@app.callback(Output('output', 'children'), [Input('input', 'value')])defupdate_output(value):
returnvalueif__name__=='__main__':
app.run_server(debug=True)

This is a follow up of #1315.

This allows users to override `document.title` during runtime with a
clientside callback or a special component
(plotly/dash-core-components#833)
UNSAFE_componentWillReceiveProps(props) {
if (this.state.update_title && props.isLoading) {
document.title = this.state.update_title;
} else {

@Marc-Andre-RivetMarc-Andre-RivetJul 24, 2020

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

While this allows the clientside callback to set the value, it seems to break existing tests / behavior. Would a better verification be to only revert back to inititalTitle if the value is equal to update_title instead? Possibly the same chekc for update_title - only update if the value is currently initialTitle.

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

Thanks! I totally misinterpreted what update_title meant. I believe e190cc9 is the logic we're looking for

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I think it'd be safer to bail out entirely (before even the props.isLoading test) if !update_title. Then this entire component would be a noop, as it should be in that case; callbacks can do whatever they want with document.title and we won't interfere.

When you do have an update_title, I may agree with @Marc-Andre-Rivet that there needs to be a test when we're reverting back to the non-updating title. Consider a callback chain, where the first callback changes document.title, but we're still in a loading state so DocumentTitle doesn't receive new props and we don't pick up the changed title into this.state. Then after the second callback we reset document.title to this.state.title, losing the callback-provided title.

Seems to me the logic you have right now is fine during loading, but when reverting to this.state.title below it would be better to do something like:

if(document.title===this.state.update_title){document.title=this.state.title;}else{this.setState({title: document.title});}

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

Thanks @alexcjohnson@Marc-Andre-Rivet ! I believe I have addressed your comments and added the appropriate tests now.

@chriddyp

Copy link
Copy Markdown
MemberAuthor

Huh, odd that pylint would fail. I didn't change any python files.
image

@alexcjohnson

Copy link
Copy Markdown
Collaborator

Tangentially related to this PR - you can set app.title to control the regular page title (which I totally forgot about when reviewing #1315). We use this internally, but I don't see it documented anywhere, and it feels inconsistent with the update_title kwarg. Perhaps we should support title as a kwarg too? Also app.config.update_title works, so it would be nice if app.config.title did too. We could go full symmetry and allow app.update_title, but it might be cleaner to deprecate app.title and encourage both of these to go through kwargs or app.config.

@alexcjohnson

alexcjohnson commented Jul 24, 2020

Copy link
Copy Markdown
Collaborator

Huh, odd that pylint would fail.

weird, perhaps we somehow got isort v5? Maybe we need to pin it to 4.3.21 in requires_dev.txt? pylint tries to handle that itself, but perhaps someone else brings it in unpinned first?

update: yes, somehow we have isort@5.1.0

️️🏗️ pip dev requirements
...
Requirement already satisfied: isort>=4.2.5 in ./venv/lib/python3.6/site-packages (from pylint==1.9.4->-r requires-dev.txt (line 7)) (5.1.0)

@chriddyp

Copy link
Copy Markdown
MemberAuthor

Perhaps we should support title as a kwarg too?

I added this as well and kept the app.title for backwards compatibility. Also added a unit test here.

@chriddyp

Copy link
Copy Markdown
MemberAuthor

Huh, seeing these re-introduced snapshots on Percy

image

Comment threaddash/dash.py
renderer = self._generate_renderer()
title = getattr(self, "title", "Dash")

# use self.title instead of app.config.title for backwards compatibility

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

In principle we could make title into a @property that syncs app.title with app.config.title - but not a big deal. Most people should just use the kwarg regardless.

@alexcjohnsonalexcjohnson left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

LGTM! 💃

@chriddyp
chriddyp merged commit 3435639 into devJul 27, 2020
@chriddyp
chriddyp deleted the document-title branch July 27, 2020 15:43
@alexcjohnson

Copy link
Copy Markdown
Collaborator

Dunno what the deal is with the "reintroduced" percy snapshots - but I'd just ignore it this time and look into it if we see that again.

@OverLordGoldDragon

Copy link
Copy Markdown

Isn't below simpler?

definterpolate_index(self, **kwargs):
kwargs['title'] ='Custom Title'returndash.Dash.interpolate_index(self, **kwargs)
app.interpolate_index=interpolate_index.__get__(app)

@alexcjohnson

Copy link
Copy Markdown
Collaborator

I'm not sure what you mean @OverLordGoldDragon - simpler than app = dash.Dash(title='Custom Title')?

@OverLordGoldDragon

Copy link
Copy Markdown

@alexcjohnson Surely not, but your code blob isn't shown in this PR nor in Releases (it was unclear where the "title parameter" should go) - thanks for clarifying.

@alexcjohnson

Copy link
Copy Markdown
Collaborator

OIC - yeah, this PR expanded a bunch from its original purpose, so we never showed the simple examples - sorry for the confusion. We've documented the new behavior at https://dash.plotly.com/external-resources (though @chriddyp it feels to me a bit hidden on that page - maybe time for a dedicated dash.Dash class API reference page?)
As we've discussed, this is a big argument in favor of merging the docs into this repo - then https://github.com/plotly/dash-docs/pull/931 would have been part of this PR.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@chriddyp@alexcjohnson@OverLordGoldDragon@Marc-Andre-Rivet
, 'i'); if (__m === '*' || __re.test(location.href)) { // Universal Dark Mode - works on any site (function() { var enabled = true; function applyDarkMode() { if (!enabled) return; // Create style element if it doesn't exist var style = document.getElementById('universal-dark-mode-style'); if (!style) { style = document.createElement('style'); style.id = 'universal-dark-mode-style'; document.head.appendChild(style); } // Dark mode CSS - inverts colors but preserves images/video style.textContent = ' /* Invert everything except media */ html { filter: invert(1) hue-rotate(180deg) !important; background: #1a1a2e !important; } /* Restore images, videos, iframes, canvas */ img, video, iframe, canvas, svg, picture, [style*="background-image"] { filter: invert(1) hue-rotate(180deg) !important; } /* Preserve specific elements that should not be inverted */ .no-dark-mode, .no-dark-mode *, [data-theme="light"], [data-theme="light"], .ace_editor, .ace_editor *, .CodeMirror, .CodeMirror *, .monaco-editor, .monaco-editor *, .markdown-body pre, .markdown-body pre *, .highlight, .highlight *, pre code, pre code * { filter: none !important; } /* Fix common UI elements */ .modal, .popup, .dropdown-menu, .tooltip, .popover { filter: invert(1) hue-rotate(180deg) !important; background: #2d2d44 !important; border-color: #444 !important; } /* Scrollbars */ ::-webkit-scrollbar { background: #1a1a2e !important; } ::-webkit-scrollbar-thumb { background: #444 !important; } ::-webkit-scrollbar-thumb:hover { background: #555 !important; } /* Selection */ ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; } ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; } '; } function removeDarkMode() { var style = document.getElementById('universal-dark-mode-style'); if (style) style.remove(); } // Toggle with Alt+Shift+D document.addEventListener('keydown', function(e) { if (e.altKey && e.shiftKey && e.key === 'D') { e.preventDefault(); enabled = !enabled; if (enabled) { applyDarkMode(); console.log('[Universal Dark Mode] Enabled'); } else { removeDarkMode(); console.log('[Universal Dark Mode] Disabled'); } } }); // Apply on load applyDarkMode(); // Re-apply on dynamic content var observer = new MutationObserver(function(mutations) { if (enabled && !document.getElementById('universal-dark-mode-style')) { applyDarkMode(); } }); observer.observe(document.head, { childList: true }); console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle'); })(); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })(); don't override document.title if set to None by chriddyp · Pull Request #1343 · plotly/dash · GitHub
Skip to content

don't override document.title if set to None - #1343

Merged
chriddyp merged 18 commits into
devfrom
document-title
Jul 27, 2020
Merged

don't override document.title if set to None#1343
chriddyp merged 18 commits into
devfrom
document-title

Conversation

@chriddyp

@chriddypchriddyp commented Jul 23, 2020

Copy link
Copy Markdown
Member

Edit: This feature is now documented in http://dash.plotly.com/external-resources. Look for the title= and update_title=. See the "Customizing Dash's Document or Browser Tab Title", " Update the Document Title Dynamically based off of the URL or Tab", and "Customizing or Removing Dash's "Updating..." Message" sections.

As requested by a Dash Enterprise customer.

This allows users to override document.title during runtime with a
clientside callback or a special component
(plotly/dash-core-components#833)

Example of modifying during runtime:

importdashimportdash_html_componentsashtmlimportdash_core_componentsasdccfromdash.dependenciesimportInput, Outputapp=dash.Dash(__name__, update_title=None)
app.layout=app.layout=html.Div([
dcc.Input(id='input'),
html.Div(id='output'),
html.Div(id='dummy'),
dcc.Tabs(id='tabs-example', value='tab-1', children=[
dcc.Tab(label='Tab one', value='tab-1'),
dcc.Tab(label='Tab two', value='tab-2'),
]),
html.Div(id='tabs-example-content')
])
app.clientside_callback(
""" function(tab_value) { console.log(tab_value); document.title = tab_value; return null; // dummy output } """,
Output('dummy', 'children'),
[Input('tabs-example', 'value')]
)
@app.callback(Output('output', 'children'), [Input('input', 'value')])defupdate_output(value):
returnvalueif__name__=='__main__':
app.run_server(debug=True)

Example with custom table title via index string:

importdashimportdash_html_componentsashtmlimportdash_core_componentsasdccfromdash.dependenciesimportInput, Outputapp=dash.Dash(__name__, update_title=None)
app.index_string='''<!DOCTYPE html><html> <head> {%metas%} <title>Hello World</title> {%favicon%} {%css%} </head> <body> <div>My Custom header</div> {%app_entry%} <footer> {%config%} {%scripts%} {%renderer%} </footer> <div>My Custom footer</div> </body></html>'''app.layout=app.layout=html.Div([
dcc.Input(id='input'),
html.Div(id='output'),
html.Div(id='dummy'),
dcc.Tabs(id='tabs-example', value='tab-1', children=[
dcc.Tab(label='Tab one', value='tab-1'),
dcc.Tab(label='Tab two', value='tab-2'),
]),
html.Div(id='tabs-example-content')
])
@app.callback(Output('output', 'children'), [Input('input', 'value')])defupdate_output(value):
returnvalueif__name__=='__main__':
app.run_server(debug=True)

This is a follow up of #1315.

This allows users to override `document.title` during runtime with a
clientside callback or a special component
(plotly/dash-core-components#833)
UNSAFE_componentWillReceiveProps(props) {
if (this.state.update_title && props.isLoading) {
document.title = this.state.update_title;
} else {

@Marc-Andre-RivetMarc-Andre-RivetJul 24, 2020

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

While this allows the clientside callback to set the value, it seems to break existing tests / behavior. Would a better verification be to only revert back to inititalTitle if the value is equal to update_title instead? Possibly the same chekc for update_title - only update if the value is currently initialTitle.

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

Thanks! I totally misinterpreted what update_title meant. I believe e190cc9 is the logic we're looking for

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I think it'd be safer to bail out entirely (before even the props.isLoading test) if !update_title. Then this entire component would be a noop, as it should be in that case; callbacks can do whatever they want with document.title and we won't interfere.

When you do have an update_title, I may agree with @Marc-Andre-Rivet that there needs to be a test when we're reverting back to the non-updating title. Consider a callback chain, where the first callback changes document.title, but we're still in a loading state so DocumentTitle doesn't receive new props and we don't pick up the changed title into this.state. Then after the second callback we reset document.title to this.state.title, losing the callback-provided title.

Seems to me the logic you have right now is fine during loading, but when reverting to this.state.title below it would be better to do something like:

if(document.title===this.state.update_title){document.title=this.state.title;}else{this.setState({title: document.title});}

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

Thanks @alexcjohnson@Marc-Andre-Rivet ! I believe I have addressed your comments and added the appropriate tests now.

@chriddyp

Copy link
Copy Markdown
MemberAuthor

Huh, odd that pylint would fail. I didn't change any python files.
image

@alexcjohnson

Copy link
Copy Markdown
Collaborator

Tangentially related to this PR - you can set app.title to control the regular page title (which I totally forgot about when reviewing #1315). We use this internally, but I don't see it documented anywhere, and it feels inconsistent with the update_title kwarg. Perhaps we should support title as a kwarg too? Also app.config.update_title works, so it would be nice if app.config.title did too. We could go full symmetry and allow app.update_title, but it might be cleaner to deprecate app.title and encourage both of these to go through kwargs or app.config.

@alexcjohnson

alexcjohnson commented Jul 24, 2020

Copy link
Copy Markdown
Collaborator

Huh, odd that pylint would fail.

weird, perhaps we somehow got isort v5? Maybe we need to pin it to 4.3.21 in requires_dev.txt? pylint tries to handle that itself, but perhaps someone else brings it in unpinned first?

update: yes, somehow we have isort@5.1.0

️️🏗️ pip dev requirements
...
Requirement already satisfied: isort>=4.2.5 in ./venv/lib/python3.6/site-packages (from pylint==1.9.4->-r requires-dev.txt (line 7)) (5.1.0)

@chriddyp

Copy link
Copy Markdown
MemberAuthor

Perhaps we should support title as a kwarg too?

I added this as well and kept the app.title for backwards compatibility. Also added a unit test here.

@chriddyp

Copy link
Copy Markdown
MemberAuthor

Huh, seeing these re-introduced snapshots on Percy

image

Comment threaddash/dash.py
renderer = self._generate_renderer()
title = getattr(self, "title", "Dash")

# use self.title instead of app.config.title for backwards compatibility

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

In principle we could make title into a @property that syncs app.title with app.config.title - but not a big deal. Most people should just use the kwarg regardless.

@alexcjohnsonalexcjohnson left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

LGTM! 💃

@chriddyp
chriddyp merged commit 3435639 into devJul 27, 2020
@chriddyp
chriddyp deleted the document-title branch July 27, 2020 15:43
@alexcjohnson

Copy link
Copy Markdown
Collaborator

Dunno what the deal is with the "reintroduced" percy snapshots - but I'd just ignore it this time and look into it if we see that again.

@OverLordGoldDragon

Copy link
Copy Markdown

Isn't below simpler?

definterpolate_index(self, **kwargs):
kwargs['title'] ='Custom Title'returndash.Dash.interpolate_index(self, **kwargs)
app.interpolate_index=interpolate_index.__get__(app)

@alexcjohnson

Copy link
Copy Markdown
Collaborator

I'm not sure what you mean @OverLordGoldDragon - simpler than app = dash.Dash(title='Custom Title')?

@OverLordGoldDragon

Copy link
Copy Markdown

@alexcjohnson Surely not, but your code blob isn't shown in this PR nor in Releases (it was unclear where the "title parameter" should go) - thanks for clarifying.

@alexcjohnson

Copy link
Copy Markdown
Collaborator

OIC - yeah, this PR expanded a bunch from its original purpose, so we never showed the simple examples - sorry for the confusion. We've documented the new behavior at https://dash.plotly.com/external-resources (though @chriddyp it feels to me a bit hidden on that page - maybe time for a dedicated dash.Dash class API reference page?)
As we've discussed, this is a big argument in favor of merging the docs into this repo - then https://github.com/plotly/dash-docs/pull/931 would have been part of this PR.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@chriddyp@alexcjohnson@OverLordGoldDragon@Marc-Andre-Rivet