this is pointing to the quill editor toolbar - javascript

I use Quilljs for a textarea on my website. The standard editor don't support image upload to the server, so i have to implement a custom handler. In the documentation is written the following:
Handler functions will be bound to the toolbar (so using this will
refer to the toolbar instance) and passed the value attribute of the
input if the corresponding format is inactive, and false otherwise.
This is actually a problem for me and i dont know how to resolve it in a clean and "right" way. I built an angular application and i have written a custom handler for image uploading. This custom image handler should upload the image with the help of an angular service to the server. The data service is globally provided in the app and a member of my component and i can access it with this.dataService. But after clicking the image upload icon in the toolbar, this is bound to the toolbar, i can't access my data service anymore. Can i avoid this boundary to the toolbar?
In explicit. Assume i have created a quill editor with the following code:
this.editor = new Quill('#editor', {
modules: { toolbar: "#toolbar"},
placeholder: 'Some Placeholder',
theme: 'snow'
});
Now i add a custom handler to the image icon with
this.editor.getModule("toolbar").addHandler("image", imageHandler);
and my handler function for instance:
imageHandler(event) {
this.dataService.addImage(event.file);
}
which uses the dataService which i've already implemented and tested. But this.dataService don't exists because this is now bind to the toolbar. I initialized the service with the constructor of the component.
constructor(private dataService: DataService) {
}
When i call this.dataService in the constructor, then it can be found and the boundary is fine, but i need to call it in my image handler function to send the file to the server.
Best regards,
Sven

The easiest way to solve this problem is to change
this.editor.getModule("toolbar").addHandler("image", imageHandler);
into
this.editor.getModule("toolbar").addHandler("image", imageHandler.bind(this));
now you can access your components variables/members in your image handler function. The toolbar have not anymore the focus.

Related

Define Web Component inside IFrame

To enhance my tinyMCE Editor, I would like to add some web components and use them inside the editor. Something similar has been done by others, but with older versions of the editor and javascript, which is not valid anymore.
I am aware, that I have to register the tag inside the editor configuration so this works already and my tag makes it to the dom. The problem is, that given components are not defined inside the editors IFrame.
I was not able to add them to the iframes window, the error message doesn't really tell why though. For Testing purposes, I also added the web component to the regular window, where it works flawlessly.
The IFrame:
<iframe srcdoc="<demo-cmp></demo-cmp>" onload="registerComponent(this)"></iframe>
<demo-cmp></demo-cmp>
The Web Component Definition:
class DemoComponent extends HTMLElement {
connectedCallback() {
alert(window.location.href);
}
}
window.customElements.define('demo-cmp', DemoComponent);
function registerComponent(iframe) {
// Exception thrown here
iframe.contentWindow.customElements.define('demo-cmp', DemoComponent);
}
The Error:
Uncaught TypeError: Custom element constructor returned a wrong element
The Fiddle:
https://jsfiddle.net/ynpks9m3/10/

Navigating back causes change detection to break in Angular elements

I am using Angular elements to use my components inside of custom ThingsBoard widgets. The elements are created inside ngDoBootstrap() like this:
const newCustomElement = createCustomElement(CustomElementComponent, {
injector: this.injector,
});
customElements.define("new-custom-element", newCustomElement);
In a ThingsBoard widget I can then import the compiled JavaScript code of my elements via the "Ressources" tab and instantiate them in the onInit() function of the widget like this:
self.onInit = function() {
element = document.createElement(
"new-custom-element");
self.ctx.$container.append(element);
}
While this works just fine and enables me to use Angular components in my widgets, I noticed a strange problem which sometimes occurs when navigating from a ThingsBoard dashboard state back to another dashboard state. Sometimes after navigating back, my widget would seem to load just fine but then the entire change detection seems to be broken. As long as I do not manually call detectChanges() in my component, the component will sometimes appear to freeze entirely in the UI and no longer react to any user interaction (such as a click event). Only refreshing the page will fix this problem.
What could cause this problem and is there anything I can do in order to fix this?
Have you ever tried like this:
ngAfterViewChecked() {
this.cd.detectChanges();
}
or
constructor(private appRef: ApplicationRef) { }
ngAfterViewInit() {
this.appRef.bootstrap(CustomElementComponent);
}
Good luck.

How to use a Dialog throught a app, passing content to it

I am building my first Vue.js app and I want to open a Dialog (using Element.io) components. I want to call a Dialog and pass the content to it.
So my dialog would be "global" and I would pass content to it from different components.
How do I include this dialog? how do I pass arguments to it and so on?
Should I use something like:
import Dialog from '../GlobalComponents/Dialog.vue';
Vue.prototype.$dialog = Dialog;
or include it in each component, and how would that be?
I have no problem making a event handler for the toggle of the Dialog, just don't know how to call the dialog to open it (or change its dialogVisible state).
You can simply add the Dialog as vue component to make it available globally.
Vue.component('my-dialog', Dialog);
Then in your "main" file / index.html or whatever you use to start your Vue app you define your dialog
<my-dialog></my-dialog>
If you want it to display errors for example you can use emits and listenters
Vue.prototype.$bus = new Vue(); // event buts
in the created method of your my-dialog
created: function() {
this.$bus.$on('error', function(msg) {
// access message here
// make dialog visible
});
}
And wherever an error occurs
this.$bus.$emit('error', 'this is my error');
If your dialog is more complex you can ofcourse also pass objects instead of strings in the emit

EmberJs - Bubble up action from modal

I have a couple of nested routes. In one of them it's possible to open a modal (which is attached to another outlet called modal).
When the user enters the text and clicks Ok, it's sent an action ('valueUpdated') to the MyrouteChildController. However, I also need to bubble this event up to MyrouteController, but it's not working. I tried returning true in the action handler and also manually calling #send.
If I call the MyrouteChildController's action from its own template it works.
http://emberjs.jsbin.com/lotinaw/edit?html,js,output
Any help would be appreciated.
Not only you can inject services in components and controllers in Ember by using Ember.inject.service() but you might also inject controllers and send actions to them using Ember.inject.controller() and then proceed with
export default Ember.Component.extend({
mycontroller: Ember.inject.controller('mycontroller'),
funcUsingControllerToSendAction(args){
let mycontroller = this.get('mycontroller');
mycontroller.send('myaction',args);
}
});
This would allow you to send action with arguments to the other controller context.

Include Javascript made from plugin into html button

We have a plugin that generates a JavaScript file. We want to run/execute this js file from within a html button, e.g.:
<input type=button value="Open js" onclick="javascript:window.open('http://jira.bltelecoms.net:8080/s/en_UScyxsyn/664/8/1.0.23-beta/_/download/batch/com.atlassian.jira.collector.plugin.jira-issue-collector-plugin:issuecollector/com.atlassian.jira.collector.plugin.jira-issue-collector-plugin:issuecollector.js?collectorId=e125274b','_self')" />
We use an third party web application called Jira and Confluence, part of the Atlassian suite. It's issue tracking software and it uses a plugin to create this JavaScript file which pops up a window, similar to a lightbox, in which you can fill in data and send it. By default it makes a trigger on the side of the page, how ever we want to execute this from a standard html button. Is there a way do do this?
You could make a new page which includes the script and open this page on click.
Or how about this:
function loadScript() {
var s = document.createElement('script');
s.src = "http://jira.bltelecoms.net:8080/s/en_UScyxsyn/664/8/1.0.23-beta/_/download/batch/com.atlassian.jira.collector.plugin.jira-issue-collector-plugin:issuecollector/com.atlassian.jira.collector.plugin.jira-issue-collector-plugin:issuecollector.js?collectorId=e125274b";
document.body.appendChild(s);
}
onclick="loadScript();"
I know that this is an old topic, but please see the following link:
https://confluence.atlassian.com/display/JIRA/Advanced+Use+of+the+JIRA+Issue+Collector#AdvancedUseoftheJIRAIssueCollector-Addingthecustomtriggerfunctionmanually
This shows how to set custom triggers for JIRA issue collectors. You will need a function to extend the global object ATL_JQ_PAGE_PROPS like below (jquery must be available).
window.ATL_JQ_PAGE_PROPS = $.extend(window.ATL_JQ_PAGE_PROPS, {
// ==== custom trigger function ====
triggerFunction : function( showCollectorDialog ) {
$('#feedback-button').on( 'click', function(e) {
e.preventDefault();
showCollectorDialog();
});
// add any other custom triggers for the issue collector here
}
});
So clicking on a DOM element with id="feedback-button" (or whatever other id you want to give it) will trigger your issue collector script.
Bear in mind the issue collector will need to specify a "Custom" trigger. You can do this by editing it in JIRA.
Hope this helps

Categories

Resources