Dash/Plotly - How do i turn off clearing value from dropdowns when using multi true? - plotly-dash

Basically, I'd like to know if it is possible to make sure a value is always selected in the dropdowns so a graph view is always available?

In your callback that generates your figures based on the dropdowns, you can simply add a check that accounts for when no dropdown options are selected.
Since you've set multi=True the value property of your dropdown will always be a list:
if not dropdown_values:
# The dropdown_values list is empty, return your graphs...
If you don't like the default Select... placeholder you can change it with the placeholder argument of dcc.Dropdown.
Alternatively if you want a certain option to stay active you could add this option back after it is cleared or after every option is cleared:
from dash import Dash
import dash_core_components as dcc
from dash.dependencies import Output, Input, State
default_dropdown_value = "MTL"
app = Dash(__name__)
app.layout = dcc.Dropdown(
id="dropdown",
options=[
{"label": "New York City", "value": "NYC"},
{"label": "Montreal", "value": "MTL"},
{"label": "San Francisco", "value": "SF"},
],
value=[default_dropdown_value],
multi=True,
)
#app.callback(Output("dropdown", "value"), Input("dropdown", "value"))
def dropdown_callback(dropdown_value):
if not dropdown_value:
return [default_dropdown_value]
return dropdown_value
if __name__ == "__main__":
app.run_server(debug=True)
Or you could add some css that targets the first option and disables pointer events:
.Select-multi-value-wrapper .Select-value:first-child {
pointer-events: none;
}
Or you could hide x's entirely. These have a Select-value-icon class you could target them with.

Related

Adding a button to Navigator to exercise a choice

Navigator contains a feature where users can define their own table views, see DAML docs for Navigator.
Is it possible to create a view where one column renders a button that, when clicked, immediately exercises a choice?
Yes, this is possible. The customized views allow you to render arbitrary React components, so let's create one to exercise a choice.
First, start with a working frontend-config.js file. The DAML quickstart project contains one.
Then, make sure you import at least the following symbols at the top of the file:
import React from 'react';
import { Button, DamlLfValue, withExercise } from '#da/ui-core';
Then, define the following top level values (for example, just below export const version={...}):
// Create a React component to render a button that exercises a choice on click.
const ExerciseChoiceButtonBase = (props) => (
<Button
onClick={(e) => {
props.exercise(props.contractId, props.choiceName, props.choiceArgument);
e.stopPropagation();
}}
>
{props.title}
</Button>
)
ExerciseChoiceButtonBase.displayName = 'ExerciseChoiceButtonBase';
// Inject the `exercise` property to the props of the wrapped component.
// The value of that property is a convenience function to send a
// network request to exercise a choice.
const ExerciseChoiceButton = withExercise()(ExerciseChoiceButtonBase)
ExerciseChoiceButton.displayName = 'ExerciseChoiceButton';
Finally, use the following code in your table cell definition:
{
key: "id",
title: "Action",
createCell: ({rowData}) => {
// Render our new component.
// The contract ID and choice argument are computed from the current contract row.
return ({
type: "react",
value: <ExerciseChoiceButton
title='Transfer to issuer'
contractId={rowData.id}
choiceArgument={
DamlLfValue.record(undefined, [
{label: 'newOwner', value: DamlLfValue.party(DamlLfValue.toJSON(rowData.argument).issuer)}
])
}
choiceName='Iou_Transfer'
/>
});
},
sortable: true,
width: 80,
weight: 3,
alignment: "left"
}
Another option would be create a React component where the onClick handler sends a REST API request using fetch(). Inspect the network traffic when exercising a choice through the Navigator UI in order to find out the format of the request.

How to toggle show/hide element in Fable?

I want to have a trivial show/hide content behavior in Fable.
Something just like this.
function myFunction() {
var x = document.getElementById("myDIV");
if (x.style.display === "none") {
x.style.display = "block";
} else {
x.style.display = "none";
}
}
<button onclick="myFunction()">Click Me</button>
<div id="myDIV">
This is my DIV element.
</div>
What is the most adequate way to do this?
This is a much larger question than you realize, because underneath it is the question of "how should I best arrange my Fable application"? The approach you've taken in your answer is roughly parallel to using JQuery in a Javascript application: you write code that directly manipulates the DOM to achieve the result you want. If that's the architectural style you've chosen — and for really simple apps, it's a perfectly good choice — then your answer can't much be improved on. The only time the "manipulate the DOM directly" approach will run into problems is if your app grows to larger-than-trivial size. At that point, you'll want a better architecture. I'll get to recommending a better architecture in a moment, but first, let me recommend a small tweak to your code. Moving the toggle function outside of toggleButton would make it more versatile:
module Markup
open System
open Fable.Helpers.React
open Fable.Helpers.React.Props
open Fable.Import
let toggleBlockElem id _ =
let contentElement = Browser.document.getElementById id
let display = if contentElement.style.display = "none" then "block" else "none"
contentElement.style.display <- display
let toggleButton text content =
let id = Guid.NewGuid().ToString()
div []
[
button [ OnClick (toggleBlockElem id) ] [ str text ]
div [ Id id ] [ str content ]
]
That allows you to reuse this function in functions like toggleLink or toggleCheckbox if you find yourself needing those.
Now, I mentioned earlier that I would recommend a different architecture if your web app gets large. The architecture I recommend is Elmish. It's based on the architecture used in Elm; if you're not familiar with it, the basic idea is similar to React. It's a model/update/view architecture. The model is an immutable data structure. There's also a message type defined; in Elmish, this is probably an F# discriminated union. The update function takes a model and a message as its two parameters, and returns a new model. The view function takes a model and a "dispatch" function as its two parameters (the "dispatch" function will be supplied by Elmish, you don't have to write it) and returns an abstract tree of HTML-like elements. Elmish then passes those elements to something like React to do the actual DOM update. (React will, essentially, diff the "old" DOM tree and the "new" DOM tree, according to a process much like the one described here for Elm).
All that is a bit much to take in, so let's look at a simple example that just toggles the visibility of a div. CAUTION: I have not tested this, just typed it in to the Stack Overflow answer box. There may be bugs in the code below; it's intended as an illustrative example rather than a working example. (For a VERY thorough working example of Elmish in action, see https://mangelmaxime.github.io/fulma-demo/ — though note that that example has an advanced architecture incorporating multiple "layers" of parent-child hierarchy in the data model, and may be hard to wrap your mind around at first glance).
Let's start with defining your data model. Since this is a trivial example, the model is similarly trivial; so trivial, in fact, that I'm going to add some extra data to it so that it actually makes sense to use a record type instead of a single bool:
type Model = { Visible: bool;
DataNotAppearingInThisFilm: int }
(A more advanced model might involve a Map<string, bool> type to keep track of the visible status of multiple divs).
The message type is also trivial, so to make it a little bit interesting we'll allow for "Show", "Hide" and "Toggle" messages:
type Msg =
| Show
| Hide
| Toggle
(The more advanced version would be Show of string, etc., passing the ID of the div to show).
The update function is similarly easy:
let update msg model =
match msg with
| Show -> { model with Visible = true }
| Hide -> { model with Visible = false }
| Toggle -> { model with Visible = not model.Visible }
Finally, the view function would look like this:
let view model dispatch =
div []
[
button [ OnClick (fun _ -> dispatch Toggle) ] [ str (if model.Visible then "Hide" else "Show") ]
div [ Display (if model.Visible then "block" else "none") ] [ str "content" ]
]
Or, pulling toggleButton out into its own function so I can show how it would work:
let toggleButton dispatch text content =
div []
[
button [ OnClick (fun _ -> dispatch Toggle) ] [ str text ]
div [ Display (if model.Visible then "block" else "none") ] [ str content ]
]
let view model dispatch =
div []
[
str "Other elements might go here"
toggleButton dispatch (if model.Visible then "Hide" else "Show") "content"
]
Notice how I needed to pass the dispatch function through as a parameter to toggleButton, so that toggleButton will be able to construct the proper behavior for its OnClick.
Putting all of this together would look like this:
open ALotOfModules
type Model = { Visible: bool;
DataNotAppearingInThisFilm: int }
type Msg =
| Show
| Hide
| Toggle
let update msg model =
match msg with
| Show -> { model with Visible = true }
| Hide -> { model with Visible = false }
| Toggle -> { model with Visible = not model.Visible }
let toggleButton dispatch text content =
div []
[
button [ OnClick (fun _ -> dispatch Toggle) ] [ str text ]
div [ Display (if model.Visible then "block" else "none") ] [ str content ]
]
let view model dispatch =
div []
[
str "Other elements might go here"
toggleButton dispatch (if model.Visible then "Hide" else "Show") "content"
]
My best attempt is to dumbly translate the JavaScript from the link in the question:
module Markup
open System
open Fable.Helpers.React
open Fable.Helpers.React.Props
open Fable.Import
let toggleButton text content =
let id = Guid.NewGuid().ToString()
let toggle _ =
let contentElement = Browser.document.getElementById id
let display = if contentElement.style.display = "none" then "block" else "none"
contentElement.style.display <- display
div []
[
button [ OnClick toggle ] [ str text ]
div [ Id id ] [ str content ]
]
To be used like Markup.toggleButton "title" "a lot of content"

Dash core component for basic Button with click event?

I'm trying to create an app with multiple tabs for different sets of information. My first thought was to use html Buttons but there's not dash_core_component for this, and I can't find documentation on anything I can use in it's place. Basically, when I click a button (or link), I'd like to get a "clicked" event with the id of the button so I can redraw the layout for the selected page.
Is there a way to do this with existing components? Is there documentation on how to create new components that can be wired into the callback system? I feel like I must be missing something obvious, but I've failed to find anything after a lot of searching.
Thanks!
In fact, they do have a click event available for a button in the latest dash_html_components, but it doesn't appear to be fully documented yet. The creator, chriddyp, has stated that the Event object may not be future-proof, but that State should be.
Using State like:
#app.callback(
Output('output', 'children'),
[Input('button-2', 'n_clicks')],
state=[State('input-1', 'value'),
State('input-2', 'value'),
State('slider-1', 'value')])
you can use values as inputs, without initiating the callback if they change -- instead waiting for the Input('button', 'n_clicks') to fire off the callback.
Copying full code example below from the link:
import dash
from dash.dependencies import Input, Output, State
import dash_html_components as html
import dash_core_components as dcc
app = dash.Dash()
app.layout = html.Div([
html.Button('Click Me', id='button'),
html.H3(id='button-clicks'),
html.Hr(),
html.Label('Input 1'),
dcc.Input(id='input-1'),
html.Label('Input 2'),
dcc.Input(id='input-2'),
html.Label('Slider 1'),
dcc.Slider(id='slider-1'),
html.Button(id='button-2'),
html.Div(id='output')
])
#app.callback(
Output('button-clicks', 'children'),
[Input('button', 'n_clicks')])
def clicks(n_clicks):
return 'Button has been clicked {} times'.format(n_clicks)
#app.callback(
Output('output', 'children'),
[Input('button-2', 'n_clicks')],
state=[State('input-1', 'value'),
State('input-2', 'value'),
State('slider-1', 'value')])
def compute(n_clicks, input1, input2, slider1):
return 'A computation based off of {}, {}, and {}'.format(
input1, input2, slider1
)
if __name__ == '__main__':
app.run_server(debug=True)
Aha! Finally found the answer, documented here: https://plot.ly/dash/urls
It would be nice to link this into the User Guide in a more obvious way (in the index?)

How to trigger click event

In simple html + js applications when I need to open dialogues of some interactive input elements (such as input[type="file"] or input[type="date"] or input[type="color"]) any non-standard way (with a button or on page load) the most strait forward way is to trigger click event on above mentioned elements. But I couldn't find a way to do that in pure elm (without ports). I see for DOM events manipulation there is focus trigger, but no click. Am I missing something? Is it not the "elm way" of doing things?
You can (ab)use the way Html.attribute can take an arbitrary string (i.e. Html.attribute "onclick" "javascript:someFunction(this)"). In some cases, this is reasonable since it can provide the least amount friction. For example, if you're wanting a button that focuses a hidden file input, and it's wrapped up nicely in a component/view file that where it's always a button followed by a file input, this makes sense:
import Html exposing (..)
import Html.Attributes as Attr exposing (..)
import Html.Events exposing (on)
filePick : Html msg
filePick =
div [ class "file-pick-wrapper" ]
[ button
[ type_ "button"
, attribute "onclick" "javascript:this.nextElementSibling.click()"
]
[ text "Choose a File" ]
, input
[ type_ "file"
, on "change" someMsgDecoder
, style [ ( "display", "none" ) ]
]
[]
]
From there you can have the someMsgDecoder use Json.Decode to read at [ "target", "files", "0", "name" ] for the filename.
Reading throught the MDN on File element I saw they suggest to use <label> to trigger the element without JavaScript:
<input type="file" id="fileElem" multiple accept="image/*" style="display:none" onchange="handleFiles(this.files)">
<label for="fileElem">Select some files</label>
elm-fileinputhttps://developer.mozilla.org/en/docs/Using_files_from_web_applications
Found a library for <input type="file">: https://github.com/lovasoa/elm-fileinput.
Also I have put up a working example using the decoder from this lib: https://runelm.io/c/ie0.

Select and 'go to selection' in Sublime

I work with files containing names to other files: stacktraces, documentation, etc.
I often need to jump to a specific file/position and to do that I select part of line containing filename, copy it, open 'go to' window and paste it and press enter.
It's working fine, but it pollutes my clipboard.
Are there any solutions to open 'go to' window with text selected already inserted there?
I've checked default keymap and found nothing like that.
Nothing built in, but you can do it with a plugin.
import sublime_plugin
class GoToFileCommand(sublime_plugin.WindowCommand):
def run(self):
window = self.window
view = window.active_view()
regions = view.sel()
if len(regions) == 1:
if not regions[0].empty():
window.run_command("show_overlay",
{"overlay": "goto", "show_files": True,
"text": view.substr(regions[0])})
return
window.run_command("show_overlay", {
"overlay": "goto", "show_files": True})
Then simply rebind ctrl/cmd+p to go_to_file.