Skip to content

Commit d01da4d

Browse files
committed
Update custom widget tutorial
1 parent a3f1770 commit d01da4d

File tree

1 file changed

+114
-174
lines changed

1 file changed

+114
-174
lines changed

docs/source/examples/Widget Custom.ipynb

Lines changed: 114 additions & 174 deletions
Original file line numberDiff line numberDiff line change
@@ -500,27 +500,26 @@
500500
"cell_type": "markdown",
501501
"metadata": {},
502502
"source": [
503-
"We want to be able to avoid user to write an invalid email address, so we need a validator using traitlets."
504-
]
505-
},
506-
{
507-
"cell_type": "code",
508-
"execution_count": null,
509-
"metadata": {},
510-
"outputs": [],
511-
"source": [
503+
"We want to be able to avoid user to write an invalid email address, so we need a validator using traitlets.\n",
504+
"\n",
505+
"```python\n",
512506
"from traitlets import Unicode, Bool, validate, TraitError\n",
513507
"from ipywidgets import DOMWidget, ValueWidget, register\n",
514508
"\n",
509+
"from ._frontend import module_name, module_version\n",
510+
"\n",
515511
"\n",
516512
"@register\n",
517513
"class Email(DOMWidget, ValueWidget):\n",
514+
" _model_name = Unicode('EmailModel').tag(sync=True)\n",
515+
" _model_module = Unicode(module_name).tag(sync=True)\n",
516+
" _model_module_version = Unicode(module_version).tag(sync=True)\n",
517+
"\n",
518518
" _view_name = Unicode('EmailView').tag(sync=True)\n",
519-
" _view_module = Unicode('email_widget').tag(sync=True)\n",
520-
" _view_module_version = Unicode('0.1.0').tag(sync=True)\n",
519+
" _view_module = Unicode(module_name).tag(sync=True)\n",
520+
" _view_module_version = Unicode(module_version).tag(sync=True)\n",
521521
"\n",
522-
" # Attributes\n",
523-
" value = Unicode('[email protected]', help=\"The email value.\").tag(sync=True)\n",
522+
" value = Unicode('[email protected]').tag(sync=True)\n",
524523
" disabled = Bool(False, help=\"Enable or disable user changes.\").tag(sync=True)\n",
525524
"\n",
526525
" # Basic validator for the email value\n",
@@ -530,7 +529,8 @@
530529
" raise TraitError('Invalid email value: it must contain an \"@\" character')\n",
531530
" if proposal['value'].count(\".\") == 0:\n",
532531
" raise TraitError('Invalid email value: it must contain at least one \".\" character')\n",
533-
" return proposal['value']"
532+
" return proposal['value']\n",
533+
"```"
534534
]
535535
},
536536
{
@@ -566,46 +566,23 @@
566566
"cell_type": "markdown",
567567
"metadata": {},
568568
"source": [
569-
"By replacing the string literal with a call to `model.get`, the view will now display the value of the back end upon display. However, it will not update itself to a new value when the value changes."
570-
]
571-
},
572-
{
573-
"cell_type": "code",
574-
"execution_count": null,
575-
"metadata": {},
576-
"outputs": [],
577-
"source": [
578-
"%%javascript\n",
579-
"require.undef('email_widget');\n",
580-
"\n",
581-
"define('email_widget', [\"@jupyter-widgets/base\"], function(widgets) {\n",
582-
" \n",
583-
" var EmailView = widgets.DOMWidgetView.extend({\n",
584-
"\n",
585-
" // Render the view.\n",
586-
" render: function() { \n",
587-
" this.email_input = document.createElement('input');\n",
588-
" this.email_input.type = 'email';\n",
589-
" this.email_input.value = this.model.get('value');\n",
590-
" this.email_input.disabled = this.model.get('disabled');\n",
569+
"By replacing the string literal with a call to `model.get`, the view will now display the value of the back end upon display. However, it will not update itself to a new value when the value changes.\n",
591570
"\n",
592-
" this.el.appendChild(this.email_input);\n",
593-
" },\n",
594-
" });\n",
571+
"```typescript\n",
572+
"export\n",
573+
"class EmailView extends DOMWidgetView {\n",
574+
" render() {\n",
575+
" this._emailInput = document.createElement('input');\n",
576+
" this._emailInput.type = 'email';\n",
577+
" this._emailInput.value = this.model.get('value');\n",
578+
" this._emailInput.disabled = this.model.get('disabled');\n",
579+
" \n",
580+
" this.el.appendChild(this._emailInput);\n",
581+
" }\n",
595582
"\n",
596-
" return {\n",
597-
" EmailView: EmailView\n",
598-
" };\n",
599-
"});"
600-
]
601-
},
602-
{
603-
"cell_type": "code",
604-
"execution_count": null,
605-
"metadata": {},
606-
"outputs": [],
607-
"source": [
608-
"Email(value='[email protected]', disabled=True)"
583+
" private _emailInput: HTMLInputElement;\n",
584+
"}\n",
585+
"```"
609586
]
610587
},
611588
{
@@ -623,106 +600,78 @@
623600
"cell_type": "markdown",
624601
"metadata": {},
625602
"source": [
626-
"To get the view to update itself dynamically, register a function to update the view's value when the model's `value` property changes. This can be done using the `model.on` method. The `on` method takes three parameters, an event name, callback handle, and callback context. The Backbone event named `change` will fire whenever the model changes. By appending `:value` to it, you tell Backbone to only listen to the change event of the `value` property (as seen below)."
627-
]
628-
},
629-
{
630-
"cell_type": "code",
631-
"execution_count": null,
632-
"metadata": {},
633-
"outputs": [],
634-
"source": [
635-
"%%javascript\n",
636-
"require.undef('email_widget');\n",
637-
"\n",
638-
"define('email_widget', [\"@jupyter-widgets/base\"], function(widgets) {\n",
639-
" \n",
640-
" var EmailView = widgets.DOMWidgetView.extend({\n",
641-
"\n",
642-
" // Render the view.\n",
643-
" render: function() { \n",
644-
" this.email_input = document.createElement('input');\n",
645-
" this.email_input.type = 'email';\n",
646-
" this.email_input.value = this.model.get('value');\n",
647-
" this.email_input.disabled = this.model.get('disabled');\n",
648-
"\n",
649-
" this.el.appendChild(this.email_input);\n",
650-
" \n",
651-
" // Python -> JavaScript update\n",
652-
" this.model.on('change:value', this.value_changed, this);\n",
653-
" this.model.on('change:disabled', this.disabled_changed, this);\n",
654-
" },\n",
655-
" \n",
656-
" value_changed: function() {\n",
657-
" this.email_input.value = this.model.get('value'); \n",
658-
" },\n",
659-
" \n",
660-
" disabled_changed: function() {\n",
661-
" this.email_input.disabled = this.model.get('disabled'); \n",
662-
" },\n",
663-
" });\n",
664-
"\n",
665-
" return {\n",
666-
" EmailView: EmailView\n",
667-
" };\n",
668-
"});"
603+
"To get the view to update itself dynamically, register a function to update the view's value when the model's `value` property changes. This can be done using the `model.on` method. The `on` method takes three parameters, an event name, callback handle, and callback context. The Backbone event named `change` will fire whenever the model changes. By appending `:value` to it, you tell Backbone to only listen to the change event of the `value` property (as seen below).\n",
604+
"\n",
605+
"```typescript\n",
606+
"export\n",
607+
"class EmailView extends DOMWidgetView {\n",
608+
" render() {\n",
609+
" this._emailInput = document.createElement('input');\n",
610+
" this._emailInput.type = 'email';\n",
611+
" this._emailInput.value = this.model.get('value');\n",
612+
" this._emailInput.disabled = this.model.get('disabled');\n",
613+
"\n",
614+
" this.el.appendChild(this._emailInput);\n",
615+
"\n",
616+
" // Python -> JavaScript update\n",
617+
" this.model.on('change:value', this._onValueChanged, this);\n",
618+
" this.model.on('change:disabled', this._onDisabledChanged, this);\n",
619+
" }\n",
620+
"\n",
621+
" private _onValueChanged() {\n",
622+
" this._emailInput.value = this.model.get('value');\n",
623+
" }\n",
624+
"\n",
625+
" private _onDisabledChanged() {\n",
626+
" this._emailInput.disabled = this.model.get('disabled');\n",
627+
" }\n",
628+
"\n",
629+
" private _emailInput: HTMLInputElement;\n",
630+
"}\n",
631+
"```"
669632
]
670633
},
671634
{
672635
"cell_type": "markdown",
673636
"metadata": {},
674637
"source": [
675-
"This allows us to update the value from the Python kernel to the views. Now to get the value updated from the front-end to the Python kernel (when the input is not disabled) we can do it using the `model.set` method."
676-
]
677-
},
678-
{
679-
"cell_type": "code",
680-
"execution_count": null,
681-
"metadata": {},
682-
"outputs": [],
683-
"source": [
684-
"%%javascript\n",
685-
"require.undef('email_widget');\n",
686-
"\n",
687-
"define('email_widget', [\"@jupyter-widgets/base\"], function(widgets) {\n",
688-
" \n",
689-
" var EmailView = widgets.DOMWidgetView.extend({\n",
690-
"\n",
691-
" // Render the view.\n",
692-
" render: function() { \n",
693-
" this.email_input = document.createElement('input');\n",
694-
" this.email_input.type = 'email';\n",
695-
" this.email_input.value = this.model.get('value');\n",
696-
" this.email_input.disabled = this.model.get('disabled');\n",
697-
"\n",
698-
" this.el.appendChild(this.email_input);\n",
699-
" \n",
700-
" // Python -> JavaScript update\n",
701-
" this.model.on('change:value', this.value_changed, this);\n",
702-
" this.model.on('change:disabled', this.disabled_changed, this);\n",
703-
" \n",
704-
" // JavaScript -> Python update\n",
705-
" this.email_input.onchange = this.input_changed.bind(this);\n",
706-
" },\n",
707-
" \n",
708-
" value_changed: function() {\n",
709-
" this.email_input.value = this.model.get('value'); \n",
710-
" },\n",
711-
" \n",
712-
" disabled_changed: function() {\n",
713-
" this.email_input.disabled = this.model.get('disabled'); \n",
714-
" },\n",
715-
" \n",
716-
" input_changed: function() {\n",
717-
" this.model.set('value', this.email_input.value);\n",
718-
" this.model.save_changes();\n",
719-
" },\n",
720-
" });\n",
721-
"\n",
722-
" return {\n",
723-
" EmailView: EmailView\n",
724-
" };\n",
725-
"});"
638+
"This allows us to update the value from the Python kernel to the views. Now to get the value updated from the front-end to the Python kernel (when the input is not disabled) we can do it using the `model.set` method.\n",
639+
"\n",
640+
"```typescript\n",
641+
"export\n",
642+
"class EmailView extends DOMWidgetView {\n",
643+
" render() {\n",
644+
" this._emailInput = document.createElement('input');\n",
645+
" this._emailInput.type = 'email';\n",
646+
" this._emailInput.value = this.model.get('value');\n",
647+
" this._emailInput.disabled = this.model.get('disabled');\n",
648+
"\n",
649+
" this.el.appendChild(this._emailInput);\n",
650+
"\n",
651+
" // Python -> JavaScript update\n",
652+
" this.model.on('change:value', this._onValueChanged, this);\n",
653+
" this.model.on('change:disabled', this._onDisabledChanged, this);\n",
654+
"\n",
655+
" // JavaScript -> Python update\n",
656+
" this._emailInput.onchange = this._onInputChanged.bind(this);\n",
657+
" }\n",
658+
"\n",
659+
" private _onValueChanged() {\n",
660+
" this._emailInput.value = this.model.get('value');\n",
661+
" }\n",
662+
"\n",
663+
" private _onDisabledChanged() {\n",
664+
" this._emailInput.disabled = this.model.get('disabled');\n",
665+
" }\n",
666+
"\n",
667+
" private _onInputChanged() {\n",
668+
" this.model.set('value', this._emailInput.value);\n",
669+
" this.model.save_changes();\n",
670+
" }\n",
671+
"\n",
672+
" private _emailInput: HTMLInputElement;\n",
673+
"}\n",
674+
"```"
726675
]
727676
},
728677
{
@@ -733,35 +682,26 @@
733682
}
734683
},
735684
"source": [
736-
"## Test"
737-
]
738-
},
739-
{
740-
"cell_type": "code",
741-
"execution_count": null,
742-
"metadata": {},
743-
"outputs": [],
744-
"source": [
685+
"## Test\n",
686+
"\n",
687+
"To instantiate a new widget:\n",
688+
"\n",
689+
"```python\n",
745690
"email = Email(value='[email protected]', disabled=False)\n",
746-
"email"
747-
]
748-
},
749-
{
750-
"cell_type": "code",
751-
"execution_count": null,
752-
"metadata": {},
753-
"outputs": [],
754-
"source": [
755-
"email.value"
756-
]
757-
},
758-
{
759-
"cell_type": "code",
760-
"execution_count": null,
761-
"metadata": {},
762-
"outputs": [],
763-
"source": [
764-
"email.value = '[email protected]'"
691+
"email\n",
692+
"```\n",
693+
"\n",
694+
"To get the value of the widget:\n",
695+
"\n",
696+
"```python\n",
697+
"email.value\n",
698+
"```\n",
699+
"\n",
700+
"To set the value of the widget:\n",
701+
"\n",
702+
"```python\n",
703+
"email.value = '[email protected]'\n",
704+
"```"
765705
]
766706
},
767707
{

0 commit comments

Comments
 (0)