Dojo Calendar Not Destroying On My Connect - javascript

Hey all, this is weird. This widget will not destroy onHide. I know the event is firing because I have placed debug code within the function that is ran. I have no idea why this won't work... it is clearly documented in the API. My code is below:
var formitem=new dijit.Calendar({
name:this.formitems.calendaritems[i].id,
id: this.formitems.calendaritems[i].id
},
dojo.create('dd',null,
this.lineitems));
dojo.connect(myself.dialog, 'onHide', function() {
formitem.destroy();
});
I keep getting the error the widget is already registered, however if the destroy function is supposed to work correctly then it is supposed to destroy the instance of it. Please help.

"the widget is already registered" error results from using a ID that's already been used. If you have to set the id, ensure that you never use the same one twice. But I would just remove that line where you set the id. Somewhere along the line you are recreating the Calendar. It's possible that you are deleting it as expected but its trying to recreate.
Note this is a bit of guess, since the example seems to be missing code that is relevant to your problem.

Related

Protractor - Jasmine . Perform some action only when a specific element is present.

I have a window-box with two buttons 'add' and 'close'. I need to test below scenario:
When clicked on 'add' button it throws error and the window remains open. I need to click on 'close' button to proceed.
I used below code:
if(element(by.xpath("xpath_of_error_box")).isEnabled())
{
element(by.xpath("xpath_of_close_button")).click();
}
But it throws below error:
No element found using locator: By(xpath, xpath_of_error_box)
Is there any way to handle this?
According to the error, it seems that your xpath locator didn't match any element. And according to the additional clarification in the question you could try:
element(by.xpath("xpath_of_error_box")).isDisplayed().then(isDisplayed => {
if (isDisplayed) {
// do what you need when it is visible
} else {
// if not then proceed
}
});
As it was pointed out, isEnabled might not be the proper method you should use in this case. If it seems that the element you try to find is always present in the dom, you might better try to check for its visibility using isDisplay instead.
An advice. It's not a good idea to use xpath locators in your tests, because this ties them to the html DOM structire of the web page you are observing. As we know, the UI happens to change often, which would make your tests to brake often as well. Although this is of cource a personal preference, it is such until you end up with tons of brocken tests after a single small change in the html.
If you need to check if an element is present you can use the following code:
if (element(by.xpath("yourXpath")).isPresent())
But your problem is not on your if code, your problem is that the xpath your are searching doesn't exist.
isEnabled() and isPresent() returns promise (not boolean) and have to be resolved.
isEnabled() could be only used for <button>.
You can use XPath all the time, don't listen to anyone.
PS. Of course it would be glad to see your HTML to check the correctness of your XPath.

Dojo 'on' event from 'byId' triggers TypeError

I have a module which contains a switch statement producing content, and a variety of on events waiting dependent on what content is inserted into the DOM and then whichever trigger is activated.
I'm finding that on event handlers using dom.byId('foo'):
on(dom.byId('foo'), touch.press, function(e){
produce the error:
Uncaught TypeError: cannot read property 'on' of null.
I can kind of understand this - if the node foo doesn't yet exist because a different switch condition has been satisfied, but i've managed to skirt this by using a css class instead:
on(query('.foo'), touch.press, function(e){
But this has the same chance of existence as the id!
I'm relatively new to Dojo, and have had "fun" getting to grips with it, and i'm interested to know why this is happening, but also if it's a Big Red Flag that i'm doing something wrong!
It's hard to say without the full code but if you want to use query you need to use this way :
require(["dojo/query"], function(query){
query(".foo").on("click", clickHandler);
});
I don't know the context of your project but if it's for mobile you maybe look at "dojo/gesture/tap" like in this exemple in the doc :
define(["dojo/on", "dojo/gesture/tap", function(listen, tap){
on(button, tap, tapHandler);
...

TypeError: this._url is undefined at Dojo FilteringSelect onChange callback

I keep getting following error: TypeError: this._url is undefined at the callback of a Dojo FilteringSelect.
I simplified my code to this:
var testFeatures = [
{ "id": 1, "Adresa": "Pyšvejcova 6, Kotěhůlky"},
...
];
var filteringSelect = new FilteringSelect({
id: "testSelect",
autoComplete: false,
searchAttr: "Adresa",
store: new Memory({ data: testFeatures }),
onChange: this.onSelected
}, "testSelect");
filteringSelect.startup();
//end of the function, still in the same define callback
onSelected: function () {
//custom processing
var queryTask = new esri.tasks.QueryTask(this.serviceUrl);
var query = new esri.tasks.Query();
query.outFields = ["OBJECTID"];
query.where = "Adresa=" + dojo.byId("testSelect").value;
query.returnGeometry = true;
queryTask.execute(query, this.zoomToSelected);
}
zoomToSelected: function (featureSet) {
//custom map processing
}
and HTML:
<input id="testSelect" data-dojo-attach-point="testSelect" />
I have no idea where's the problem, Google found no case similar to mine. FireBug says the error occurs in init.js. Console says line 199, but the code in question (...nction(){},onExecuteForCountComplete:function(){},onExecuteForExtentComplete:fun...) is on line 256.
One possible cause of problems might be ArcGIS JavaScript API or Web AppBuilder - this seems not to be one of the "ArcGIS-heavy" parts of the code, but I don't know for sure. It's ArcGIS JS API 3.15 (Dojo 1.10) and Web AppBuilder for developers version 1.4.
EDIT: with help of #KenFranqueiro and this post I made some progress. I can't say that I fully understand the onChange callbacks, but I learnt to omit the parentheses while calling a named function. The onSelected still wasn't called, but modifying the input data to include id solved this. But it didn't solve the main problem...
Now the old good TypeError: this._url is undefined occurs at queryTask.execute, or between it and start of zoomToSelected method. The exact place where the error occurs changed to line 256, column 351, with following referenced code:
...e:function(a,b,c,d,f){var m=f.assembly;a=this._encode(n.mixin({},this._url.query...
There is a pointer at the = after "a", so the error seems to be to the right of it, trying to mixin something non-existent to something else. I have no idea what the this in the init.js should mean. Unfortunately, dojo core code is almost undebuggable without some de-obfuscation. Is this my only option, or does anybody know how to solve it?
So debugging the init.js wasn't so hard, it takes QueryTask as this. As far as I know, this shouldn't have a _url attribute. So I must have some mistake in the queryTask as well.
Obsolete part of the question, archived:
I wonder whether the problem might be caused by the onChange callback's argument, which I don't really understand. I've read several examples of Dojo FilteringSelect with onChange event set, like the official one. Usually it has some argument, but I don't know what does it mean and where it gets from. In the official example it corresponds to the div id and nothing else. However, how is the id translated to a variable and even whether my assumption that it's the id is correct. The detailed documentation is not much helpful in this case.
Older EDIT: testSelect is an object. Seems it was created implicitly with the dom - it's a childnode of this.domNode. So now I understand where it comes from, but not how to prepare another function to be called on change and why the correct syntax is what it is.
Also, I don't know where exactly is the problematic undefined this._url supposed to exist. In my example, this refers to the dijit, but I have no idea what is the scope of the part of init.js where the problem occurs.
I'm not sure how much related are the two subquestions (confusion in the onChange callback and identification of this in init.js), I only suppose they are symptoms of the same issue since the error is thrown at the onChange event in my code.
The problem at the query was caused by this.serviceUrl either missing as a part of wrong coontext, or being an object instead of a URL string. So the final step was to make sure the correct context is used (by lang/hitch) and then setting this.serviceUrl to be what I originally thought, one of the attributes of the object referenced as serviceUrl before.

Firebreath Object in AngularJS

I have tried to include a FireBreath plugin object in an AngularJS view, however when I try to render the view I get this error:
TypeError: Cannot read property 'nodeName' of undefined
I am able to successfully include the object in the view with $compile like this:
$("body").append($compile('<object id="plugin" type="application/x-firebreathplugin" width="0" height="0></object>')($scope));
However, after including the object like this I cannot get my plugin to fire an event in the JS.
Doing something like this:
plugin = document.getElementById('plugin');
console.log(plugin);
Returns
TypeError
In the Chrome console. But I can still do:
plugin.callFunction();
And have a FireBreath method execute. The issue is when I try to get an event to fire in the JS. No matter what I try, I cannot get the event to fire. So this code will never execute:
var addEvent = function(obj, name, func) {
obj.addEventListener(name, func, false);
}
addEvent(document.getElementById('plugin'), 'firebreathEvent', function(data) {
console.log('data ' + data);
});
var plugin = document.getElementById('plugin');
plugin.functionThatTriggersFireBreathEvent();
Does anybody know if it has something to do with accessing the object after calling $compile? I noticed that in regular HTML (before using AngularJS) logging the plugin in the console returns this :
<JSAPI-Auto Javascript Object>
So I am thinking that whatever I am getting with document.getElementById after using $compile is not the same.
What would be easier is is if I could just include the <object> tag in the view.html file and have it display in <body class='ng-view'> but I get the top TypeError, so if anyone has any ideas for that, that would be preferred.
Any help is appreciated. Thanks.
If anyone is interested, because I could not get the event to fire, I followed along to this link:
http://colonelpanic.net/2010/12/firebreath-tips-asynchronous-javascript-calls/
(which I think is your blog #taxilian) to get the data back to the JS.
Plugin Code: Great example in the link.
JS Code:
//attach FireBreath Object to AngularJS View
$("body").append($compile('<object id="plugin" type="application/x-firebreathplugin" width="1" height="1"><param name="onload" value="pluginLoaded"/></object>')($scope));
var callback = function(data) {
//data is an object
console.log(data.resultFromFireBreath);
}
plugin = document.getElementById("plugin");
plugin.getData(callback);
This will have to work for now until someone can figure out how to attach an event to the plugin object after $compile.
I ran into the same problem and was able to make the problem go away by creating a read-only nodeName property in my plugin object. I asked about this in a firebreath forum post and taxilian suggested adding this to JSAPIAuto.cpp, which also worked, so I submitted a pull request with the change.
I once spent about 6 hours trying to make FireBreath plugins work with jquery; it was really educational, but ultimately I determined that it wasn't worth the work.
Long story short is that it's not worth it; particularly since even if you could make it work, it would break on IE9 where FireBreath doesn't support addEventListener (IE never gives it the even info, so it's a little hard to support) and you would need to use attachEvent anyway.

dojo dijit.Dialog destroy underlay error

I have a class that extends dijit.Dialog but only to set default functionality and buttons for my site. When clicking the dialog's cancel button the following code is run:
this.actionDialog.destroyRecursive();
this.actionDialog.destroy();
nb this.actionDialog = dijit.Dialog
Sometimes (not always) the following error gets thrown:
Uncaught TypeError: Cannot call method 'destroy' of undefined
DialogUnderlay.xd.js:8
Which causes following dialogs to incorrectly display. I am using 1.5 from Google API's. Am I missing something with the underlay code?
Error thrown after Ken's answer:
exception in animation handler for: onEnd
TypeError: Cannot read property 'style' of null
Both from dojo.xd.js:14. But the code still works properly.
I'm still not entirely sure what the problem is, other than for some reason dijit.DialogUnderlay code is getting confused. FWIW, this doesn't happen in Dojo 1.6.
While I was poking at some potential solutions, I seemed to accidentally find out that avoiding this problem is perhaps as easy as calling hide() on the dialog immediately before destroying it, e.g.:
this.actionDialog.hide();
this.actionDialog.destroyRecursive();
Alternatively, you might be interested in hiding the dialog, then destroying it once the hide animation finishes.
Here's how you can do it on Dojo 1.5 and earlier (tested 1.3+):
dlg.connect(dlg._fadeOut, 'onEnd', function() {
this.destroyRecursive();
});
dlg.hide();
In 1.6, the fadeOut animation is no longer exposed on the instance (granted, it was technically private earlier anyway), but onHide now triggers once the animation ends (whereas before it triggered as soon as it began). Unfortunately a setTimeout is needed to get around an error that occurs due to other code in the branch calling onHide, which assumes that something still exists on the instance which won't after we've destroyed it (see #12436).
dlg.connect(dlg, 'onHide', function() {
setTimeout(function() { dlg.destroyRecursive(); }, 0);
});
dlg.hide();
See it in action on JSFiddle: http://jsfiddle.net/3MNRu/1/ (See the initial version for the original error in the question)
The dialog.hide() method returns a Deferred, your code can be something more readable like this:
var dialog = this.actionDialog;
dialog.hide().then(function(){ dialog.destroyRecursive(); });
Be careful not to do this:
this.actionDialog.hide().then(function(){ this.actionDialog.destroyRecursive(); });
At the context of then this has another meaning!
You only need to call destroyRecursive()
The second destroy command is what is probably causing the error, and the error probably is causing the issues with other dialogs.
http://dojotoolkit.org/api/1.3/dijit/_Widget/destroyRecursive
destroyRecursive
Destroy this widget and it's descendants. This is the generic "destructor" function that all widget users should call to cleanly discard with a widget. Once a widget is destroyed, it's removed from the manager object.
I was getting the IE8 error : 'this.focusNode.form' is null or not an object. I found this was the result of the dialog.hide() returning a deferred. I wrote my own _closeDialog which eliminated the IE error.
_closeDialog : function(cntxt){
cntxt.popup.hide().then(
function(){
cntxt.popup.destroyRecursive(false);
cntxt.popup.destroy(false);
cntxt.destroyRecursive(false);
cntxt.destroy(false);
});
},

Categories