how to hide dojo validation error tooltip? - dojo

I'm using dojo to validate input fields and if there is an error (for eg: required field) it appears in the dojo tooltip. But, I would like to show error in the custom div instead of tooltip.
So, I'm wondering if there is a way to hide/disable the validate error to appear in the tooltip? If so, I can capture the error message shown in the hidden tooltip and show the result in custom div, which will be consistent with error styling across the application.
Please advise. Thanks.

I would recommend to use the standard Dojo validation mechanism, contrary to what vivek_nk suggests. This mechanism works great in most cases, and covers most situations (required, regular expressions, numbers, dates etc.).
To solve your issue: you can overrule the "dispayMessage" function of a ValidationTextBox (for example).
displayMessage: function(/*String*/ message){
// summary:
// Overridable method to display validation errors/hints.
// By default uses a tooltip.
// tags:
// extension
if(message && this.focused){
Tooltip.show(message, this.domNode, this.tooltipPosition, !this.isLeftToRight());
}else{
Tooltip.hide(this.domNode);
}
}
Just create your own ValidationTextBox widget, extend dijit/form/ValidationTextBox, and implement your own "displayMessage" function.

Simple solution for this scenario is not to add the "required" condition at all to those fields. Instead add a separate event handler or function to check for this validation.
For eg: add a function for onBlur event. Check if the field is a mandatory. If so, show message in the custom div as expected.
<input data-dojo-type="dijit/form/TextBox"
id="sampleText" type="text" mandatory="true" onBlur="checkMandatory(this)"/>
function checkMandatory(field) {
if(field.mandatory=='true' && field.value=="") {
alert('value required'); // replace this code with my showing msg in div
} else {
field.domNode.blur();
}
}
This above code snippet does not use Dojo for validation, rather manual. Dojo actually helps to ease this by just adding the attribute "required". If that is not required, then just ignore Dojos help for this case and go native.
So, for all fields, just add the attributes - "mandatory" & "onBlur", and add the above given function for onBlur action for all these fields.

Related

CKEditor 5 copy selected content from one editor to another

I have two editors on the screen, one read-only. What I want to do is allow the user to select content from the read-only editor and paste it into the current position of the other by clicking a button. (the logic may manipulate the text which is one reason I don't want to use the system's clipboard.)
So far I have the function that is able to paste the text like as follows. (I am using the Angular wrapper which explains the presence of the CKEditorComponent reference.
doPaste(pasteEvent: PasteEvent, editorComponent: CKEditorComponent) {
const editor = editorComponent.editorInstance;
editor.model.change(writer => {
writer.insertText(pasteEvent.text, editor.model.document.selection.getFirstPosition() );
});
}
What I can't find from the documentation is how to extract the selected text. What I have so far is:
clickPasteSelectedPlain(editorComponent: CKEditorComponent) {
const editor = editorComponent.editorInstance;
const selection = editor.model.document.selection;
console.log('clickPasteAll selection', selection);
console.log('clickPasteAll selectedcontent', editor.model.document.getSelectedContent);
}
The selection appears to change depending on what is selected in the editor's view. The getSelectedContent function is undefined. How do I get the content?
With a bit of poking around I figured out how to do this. I'll document it here on the chance that it will help someone down the road avoid the process of discovery that I went through.
On the source document I have a ckeditor element like this:
<div *ngIf="document">
<ckeditor #ckEditor
[editor]="Editor" [config]="ckconfig" [disabled]="true"
[(ngModel)]="document.text"></ckeditor>
<button mat-flat-button (click)="clickPasteSelectedPlain(ckEditor)">Paste Selected Text Plain</button>
</div>
In the component the function called on the click event is like this:
#Output() paste = new EventEmitter<PasteEvent>();
...
clickPasteSelectedPlain(editorComponent: CKEditorComponent) {
const editor = editorComponent.editorInstance;
this.paste.emit({
content: editor.model.getSelectedContent(editor.model.document.selection),
obj: this.document,
quote: false
});
}
The PasteEvent is defined as an exported interface which I will omit here to save space. The content key will refer to a DocumentFragment.
Note that I am passing the CKEditorComponent as a parameter. You could also access it via an Angular #ViewChild declaration but note that my ckeditor is inside an *ngIf structure. I think that works well in Angular 6 but in the past I have had difficulty with #ViewChild references when the target was conditionally in the DOM. This method always works but use whatever method you want.
The event fired by the emit is processed with a method that looks like this:
doPaste(pasteEvent: PasteEvent, editorComponent: CKEditorComponent) {
const editor = editorComponent.editorInstance;
editor.model.insertContent(pasteEvent.content);
}
Because the content is a DocumentFragment the paste operation will include all formatting and text attributes contained in the selected source. But that's all there is to it.

Binding list to a HTML textbox is not updating the view

In Aurelia, I have a textbox like this:
<input type="text" value.bind="contact.topics|commaList">
Where commaList is a value converter:
export class CommaListValueConverter {
toView(value) {
return value.join('|')
}
fromView(value) {
return value.split('|')
}
}
There are two things:
Updating the list (contact.topics) from code doesn't change anything in the view. Tried forcing two-way as well. The toView() is not called (tried to log calls). For comparison, in my view there is also a regular repeat topic of contact.topics which update fine.
Aurelia modifies my contact.topics list by adding an element __array_observer__: ModifyArrayObserver to my list. So now I somehow have to clean my list of such unwanted elements before saving (or dirty checking).
I update the array this way:
this.contact.topics.push('test')
The contents of the array display correctly in the for of loop (not shown).
gist
https://gist.run/?id=dd11c5837b77b29b586d2c4f978a7a48
Aurelia bindings don't react on Array and Object internal changes unfortunately.
You can't escape the __ private properties that aurelia adds for observation but since you are dirty checking an array you can take a clean clone of it with arr.slice()

How to click dijit.form.Button programmatically

I have form and input inside.
<input type="submit" label="Upload" data-dojo-type="dijit.form.Button" data-dojo-attach-point="leftLogoSubmit" id="leftLogoSubmit"/>
Is it possible push this button programmatically?
I tried
this.leftLogoSubmit.onclick();
but it not works.
Uncaught TypeError: this.leftLogoSubmit.onclick is not a function
You need to use on.emit().
It can be done in 2 ways:
As #tik27 stated:
dijit.registry.byId("leftLogoSubmit").emit('click', { cancelable:true, bubbles: true})
Note the 2 properties on the object. Without this, the click will not work properly.
You can also do:
on.emit(dojo.byId("leftLogoSubmit"), 'click', { cancelable:true, bubbles: true})
Where on is required as dojo/on
Last but not least, you can call the onClick method of the button directly (like #frank proposed):
dijit.registry.byId("leftLogoSubmit").onClick();
Difference is:
- in 1st case the widget is use to access the emit method (only works with Evented widgets)
- in 2nd case dojo/on is used so we need to pass the button domNode instead of the widget
- in 3rd it is not a native click (so will not bubble). It just call the button click handler
You can write like this
this.leftLogoSubmit.on("click", function() {
// Your code
});
you can fire the click function as.
this.leftLogoSubmit.onClick();
note: the capital C in the onClick.
You can go with core JavaScript solution
document.getElementById("leftLogoSubmit").click();

how to attach an event to dojox.mobile.heading 'back' button

In addition to the 'back' button functioning as expected, I need to asynchronously invoke a function to update some db tables and refresh the UI.
Prior to making this post, I did some research and tried the following on this...
<h1 data-dojo-type="dojox.mobile.Heading" id="hdgSettings" data-dojo-props="label:'Settings',back:'Done',moveTo:'svStart',fixed:'top'"></h1>
dojo.connect(dijit.registry.byId("hdgSettings"), "onclick",
function() {
if (gblLoggerOn) WL.Logger.debug(">> hdgSettings(onclick) fired...");
loadTopLvlStats();
});
Since my heading doesn't have any other widgets than the 'back' button, I thought that attaching this event to it would solve my problem... it did nothing. So I changed it to this...
dojo.connect(dijit.registry.byId("hdgSettings")._body, "onclick",
function() {
if (gblLoggerOn) WL.Logger.debug(">> hdgSettings(onclick) fired...");
loadTopLvlStats();
});
As it turns out, the '._body' attribute must be shared by the Accordion widget that I just happen to use as my app's main UI component, and any attempt to interact w the Accordion rendered my entire app useless.
As a last resort, I guess I could simply forgo using the built-in 'back' button, and simply place my own tabBarButton on the heading to control my app's transition and event processing.
If the community suggests that I use my own tabBarButton, then so be it, however there has to be a way to cleanly attach an event to the built-in 'back' button support.
Thoughts?
The following should do the trick:
var backButton = dijit.registry.byId("hdgSettings").backButton;
if (backButton) {
dojo.connect(backButton, "onClick", function() { ... });
}
Remarks:
The code above should be executed via a dojo/ready call, to avoid using dijit's widget registry before it gets filled. See http://dojotoolkit.org/reference-guide/1.9/dojo/ready.html.
Note the capitalization of the event name: "onClick" (not "onclick").
Not knowing what Dojo version you use (please always include the Dojo version information when asking questions), I kept your pre-AMD syntax, which is not recommended with recent Dojo versions (1.8, 1.9). See http://dojotoolkit.org/documentation/tutorials/1.9/modern_dojo/ for details.

Dojo Dijit: Why does attr("required", true) fail to set the style "dijitRequired"? or Is there another class which indicates a Dijit is required?

As far as I can judge, the CSS-Rule "dijitRequired" is used to mark a required input field. Yet, this style is not set when I apply the "required"-Attribute to a dijit, for example, a date dijit:
The Dijit is built as follows:
<input dojoType="dijit.form.DateTextBox" class="l" id="datumsTestID" name="datumsTest" tabindex="5" value="2009-01-01" />
The Attribute is set with the following Javscript code
dijit.byId('datumsTestID').attr('required', true)
Am I doing something wrong or is the style "dijitRequired" not intended to be used as I assume?
For my purposes, I patched ValidationTextBox.js to set/unset the class, but is there a cleaner (meaning: more correct) way to set the class or can I style required fields using other attributes?
ValidationTextBox.js, Dojo 1.3, Line 116
_setRequiredAttr:function(_12){
this.required=_12;
if (_12) dojo.addClass(this.domNode, "dijitRequired");
else dojo.removeClass(this.domNode, "dijitRequired");
dijit.setWaiState(this.focusNode,"required",_12);
this._refreshState();
}
Hmm, I don't see that code in ValidationTextBox.js or anywhere else. My _setRequiredAttr() in 1.3 is:
_setRequiredAttr: function(/*Boolean*/ value){
this.required = value;
dijit.setWaiState(this.focusNode,"required", value);
this._refreshState();
}
Actually I don't see any references to dijitRequired at all, maybe that's something you added to your local copy?
Setting dijitRequired is not enough. dijit.form.DateTextBox has its own internal state. Even if required attribute is set, this widget display error only when it has been blurred. You can disable this mechanism using such subclass:
dojo.provide("my.DateTextBox");
dojo.require("dijit.form.DateTextBox");
dojo.declare("my.DateTextBox", dijit.form.DateTextBox, {
_setRequiredAttr: function(required){
this._hasBeenBlurred = true;
this.inherited(arguments);
}
});