dijit widgets inside a custom widget -- handling their events - dojo

JS:
define(["dojo/_base/declare","dojo/dom",
"dijit/_Widget", "dijit/_TemplatedMixin",
"dojo/text!./templates/MainViewWidget.html",
"dijit/layout/TabContainer", "dijit/layout/ContentPane","dijit/layout/BorderContainer","dijit/form/TextBox", "dijit/layout/AccordionContainer"],
function(declare, dom, _Widget, _TemplatedMixin, template){
return declare("package.MainViewWidget", [_Widget, _TemplatedMixin], {
widgetsInTemplate: true,
templateString: template,
constructor: function(){
},
startup: function(){
},
search: function(evt){
alert('hi');
alert(evt);
}
});
});
templates/MainViewWidget.html:
<div class="mainContainer">
<div data-dojo-type="dijit.layout.BorderContainer" data-dojo-props="design:'sidebar', gutters:true, liveSplitters:true" style="width:100%;height:100%;">
<div data-dojo-type="dijit.layout.ContentPane" data-dojo-props="region:'left', splitter:true">
<h2>List of trips</h2>
<br />
<input type="text" data-dojo-type="dijit.form.TextBox" data-dojo-props="placeHolder:'Search...'" data-dojo-attach-event="onchange:'search'"/>
<br />
</div>
<div data-dojo-type="dijit.layout.TabContainer" data-dojo-attach-point="tabContainerDiv" data-dojo-props="region: 'center', tabPosition: 'top', tabStrip:'true', style:'width:80%;height:100%'">
<div data-dojo-type="dijit.layout.ContentPane" title="Summary" data-dojo-props="selected:'true', title:'About'">Welcome. Navigate through the Left pane.</div>
</div>
</div>
</div>
The thing is, I want to capture events on the TextBox. I was looking to do this with just markup as you can see from data-dojo-attach-event="onchange:'search'". I have tried many variations of this and I can't get it to work. Basically what I want is to define a function in JS and attach it as handler in the markup. Please help.

This isn't supported, sadly. I just spent about two hours discovering this. Any node in your template with a data-dojo-type attribute is ignored by _TemplatedMixin._attachTemplateNodes (see line 177). In other words, data-dojo-attach-event will only bind to plain DOM nodes (not Dijits).
This at least applies to v1.8. The attach processing is different in v1.9 (there's an _AttachMixin), so it might work there.

Try:
data-dojo-attach-event="onChange:search"
Camelcase onChange, and no quotes around search.

Related

How to fix my simple custom v-on directive that does not execute a method immediately?

I am here to ask some help about why is my custom directive not working properly. I am trying to create my own v-on (named v-myOn) directive that would just change the background color of the text when it is clicked. The problem is that the method is executed instantly when vue js application is started (meaning the element background has the color style already) and not when a certain event happened which is when the element is clicked. Thanks in advance!
Update: Problem as what Phil stated is I execute the function directly in the template. But in this case I am trying to pass an argument to the method changeColor. So how could i prevent it from executing while being able to pass arguments?
Here is my code in App.vue:
<template>
<div class="container">
<div class="row">
<div class="col-xs-12 col-sm-8 col-sm-offset-2 col-md-6 col-md-offset-3">
<h1 v-myOn:click="changeColor('blue')" :style="{background: color}" ref="heading">Directives Exercise</h1>
<!-- Exercise -->
<!-- Build a Custom Directive which works like v-on (Listen for Events) -->
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return{
color: ''
}
},
directives: {
myOn : {
bind(el, binding, vnode) {
el.addEventListener(binding.arg, binding.value)
}
}
},
methods: {
changeColor(color)
{
this.color = color;
}
}
}
</script>
<style>
</style>
You have to wrap in an arrow function otherwise it will get executed immediately as you have discovered and #Phil has pointed out.
<h1 v-myOn:click="() => changeColor('blue')" :style="{background: color}" ref="heading">Directives Exercise</h1>

why is Vuejs disabling the ability of a media query to add and remove component

Given i have this
//mycompoent.js
Vue.component('main-nav',{
template:`
<div id="main-nav">
</div>
`
});
Vue.component('menu-nav',{
template:`
<div id="menu-nav">
</div>
`
});
new Vue({
}).$mount("#nav-app");
Then in my CSS I have the following
//style.css
#menu-nav{display:none;}
#media (max-width:840px){
#main-nav{display:none;}
#menu-nav{display:block;}
}
//index.html
<div id="nav-app">
<main-nav />
<menu-nav />
</div>
When I resize the browser less than 840px the menu-nav component never appears; I don't know what I have done wrong.
If you're testing this directly in the browser (without a compile step), you can't use the self-closing form <main-nav /> for components. Try the following:
<div id="nav-app">
<main-nav></main-nav>
<menu-nav></menu-nav>
</div>

Dojo changing scope of data dojo attach point

Can you specify/change the scope of a data-dojo-attach-point to something other than the current widget?
eg. I have a templated widget called parent. In that template I have another widget called child1. Nested in child1, I have some widgets. I want to bind these nested widgets to child1 rather than parent.
Edit:
<div data-dojo-type="someContainer" data-dojo-attach-point="parent">
<div data-dojo-type="somePane" data-dojo-attach-point="child1">
<span data-dojo-attach-point="(I want to be bound to somePane)"></span>
</div>
</div>
I'd like to bind the "span" to somePane without having to go through someContainer.
Separate the span into it's own widget and you can add them to the parent like this.
Parent template that contains the content panes
<div style="width: 100%; height: 100%;">
<div data-dojo-type="dijit/layout/LayoutContainer" style="width: 100%; height: 100%" data-dojo-attach-point="mainNode">
<div data-dojo-type="dijit/layout/ContentPane" data-dojo-props="region:'top'" >
<div >
<!--some content-->
</div>
</div>
<div data-dojo-type="dijit/layout/ContentPane" data-dojo-props="region:'center'" id="center">
<div data-dojo-attach-point="centerNode"></div>
</div>
</div>
</div>
In postCreate method of your parent widget create new instance of the child and attach it to the parent
define([
"dojo/_base/declare",
"dijit/_WidgetBase",
"dijit/_TemplatedMixin",
"dijit/_WidgetsInTemplateMixin",
"dojo/text!./templates/Parent.html",
"somePath/childWidget",
'dojo/domReady!'
], function (
declare,
_WidgetBase,
_TemplatedMixin,
_WidgetsInTemplateMixin,
parentTemplate,
ChildWidget
) {
return declare([_WidgetBase, _TemplatedMixin, _WidgetsInTemplateMixin], {
templateString: parentTemplate,
postCreate: function () {
this.inherited(arguments);
var myChild = new ChildWidget();
myChild.placeAt(this.centerNode);
myChild.startup();
}
});
});
Then because the span is inside it's own widget, you might have a template for it that looks like this
<div>
<span data-dojo-attach-point="spanNode"></span>
</div>
So now the span attach point is decoupled from the parent. You can directly reference the 'spanNode' from within the widget you created for the span.
Declaratively,
in your childWidget that contains the span you can give give it a class name like this
return declare("childWidget", [_WidgetBase, _TemplatedMixin, _WidgetsInTemplateMixin], { ...
And in the parent template instead of using an attach point to attach the widget use data-dojo-type like this
<div data-dojo-type="dijit/layout/ContentPane" data-dojo-props="region:'center'" id="center">
<div data-dojo-type="childWidget"><!--child widget will get attached here--></div>
</div>

Dojo loading templated widget into data-dojo-type

I've created a very simple HTML templated widget.
<div class="tool">
<a href="" id="freehand">
<i class="flaticon-writing9"></i>
</a>
</div>
<div class="tool">
<a href="" id="polygon">
<i class="flaticon-constellation"></i>
</a>
</div>
My widget declaration looks like this:
define([
"dojo/_base/declare",
"dijit/_WidgetBase",
"dijit/_TemplatedMixin",
"dojo/text!./templates/DrawingToolsWidget.html",
"dojo/parser",
"dojo/ready"
],
function(declare, _WidgetBase, _TemplatedMixin, template, parser, ready) {
return declare("DrawingToolsWidget",[_WidgetBase, _TemplatedMixin], {
templateString: template,
constructor: function() {
console.log(this);
}
});
ready(function(){
parser.parse();
});
}
);
I try to attach it to a point in my main DOM with a data-dojo-type attribute:
<div id="drawing-tools-container" data-dojo-type="DrawingToolsWidget"></div>
But I keep getting a generic dojo/parser::parse() error Error {} which is completely useless for debugging.
My directory structure is: /index.html(main DOM) /app/DrawingToolWidget/templates/DrawingToolsWidget.html(template) /app/DrawingToolWidget/DrawingToolWidget.js(declaration)
I've also tried to attach "app/DrawingToolWidget/DrawingToolWidget" just in case it wanted the path to the widget declaration. Nope.
What am I doing wrong? Why is it so hard just to attach a fragment of markup to the DOM?
Your template is invalid because you can only have 1 root element. I'm not sure if that's the main problem, but this might solve certain things. A quote from the documentation:
Note that when you define a template, it can only have one root
node definition ( just like with XML documents). Multiple nodes at the
top level is not allowed.
The article: http://dojotoolkit.org/documentation/tutorials/1.9/templated/
A working template would be:
<div>
<div class="tool">
<a href="" id="freehand">
<i class="flaticon-writing9"></i>
</a>
</div>
<div class="tool">
<a href="" id="polygon">
<i class="flaticon-constellation"></i>
</a>
</div>
</div>
The working example can be found here.
About your debugging problem, do you use Google Chrome? When encountering an error, you should try to close and open the developer tools/console, if you do that, there should be a small arrow next to the Error, for example:
As you can see here, there are 2 arrows, the left one gives you the stacktrace, while the right one (almost at the end of the error line), will give you detailed information about the error (if you click/expand it).

dojo.connect no longer working with forms?

I was using something like this before Dojo 1.8, but now I get a "node not found" error :
<form dojoType="dijit.form.Form">
Search :
<input type="text" dojoType="dijit.form.TextBox" name="searcht" id="searcht">
<script type="dojo/connect" event="onSubmit" args="evt">
my_function();
dojo.stopEvent(evt);
</script>
</form>
I noticed that if I remove the search text box the code is working.
How can I rewrite the above to work with 1.8, and also please be so kind to point me in the right direction to read about this and understand why this is happening.
I should also note that I'm using the same type of code for contentpanes, and the code works fine there.
Thanks,
Noru
In dojo 1.8 dojo.connect is dojo/on. First you have to load the modules you are going to use and parse the file to transform dijit elements.
<script>
require([
"dojo/parser",
"dijit/form/Form",
"dijit/form/TextBox",
"dijit/form/Button"
], function(parser) {
parser.parse();
});
</script>
Second, declare the dijit properties and funcionality inside html tags:
<div data-dojo-type="dijit/form/Form" id="search_form">
<script type="dojo/on" data-dojo-event="submit" data-dojo-args="evt">
evt.stopPropagation();
alert( "my_function()" );
</script>
<label for="my_textbox">Search:</label>
<input type="text" data-dojo-type="dijit/form/TextBox" id="my_textbox"/>
<button data-dojo-type="dijit/form/Button" id="my_button" type="submit">
Submit
</button>
</div>
I used a declaratively example inserting dijit options inside the html code. There is other way using only javascript. Take a look in the official documentation: http://dojotoolkit.org/reference-guide/1.8/dijit/index.html