Polymer - databinding within window.addEventListener for 'deviceorientation' - polymer-2.x

Please refer below polymer 2.0 element.
<link rel="import" href="../../bower_components/polymer/polymer-element.html">
<dom-module id="xxx">
<template>
<style>
:host {
display: block;
};
</style>
<div>sdsds {{alphaValue}}</div>
<div>sdsd [[betaValue]]</div>
<div>sdsd [[gammaValue]]</div>
</template>
<script>
class xxxClass extends Polymer.Element {
static get is() { return 'xxx'; }
static get properties() {
return {
alphaValue:{
type: Number,
value: 0.0
},
betaValue:{
type: Number,
value: 0.0
},
gammaValue:{
type: Number,
value: 0.0
}
};
}
ready(){
super.ready();
}
connectedCallback() {
super.connectedCallback();
window.addEventListener('deviceorientation',this.getSensorData,true);
}
disconnectedCallback() {
super.disconnectedCallback();
window.addEventListener('deviceorientation',this.getSensorData,true);
}
getSensorData() {
this.alphaValue= event.alpha;
this.betaValue = event.beta;
this.gammaValue = event.gamma;
}
}
window.customElements.define(xxxClass .is, xxxClass );
</script>enter code here
</dom-module>
In the above element, i am not able to bind the properties from the event. Please suggest what i am doing wrong in this element.
In the same element i tried binding property with paper-slider , it is working find ( this code is not included in the snippet )

There is maybe multiple issue on your code :
{{alphaValue}} The two way binding is not useful in that case, just use like the other [[alphaValue]]
On the callback function for the listener, you have to bind the context. That will be window.addEventListener('deviceorientation', this.getSensorData.bind(this), true);. If you don't do that during you callback function process, the values this.alphaValue, this.betaValue and this.gammaValue will be null.
On your callback function you missed a parameter for the event. getSensorData(event)
So the code will look like to :
<dom-module id="os-test">
<template>
<div>sdsds {{alphaValue}}</div>
<div>sdsd [[betaValue]]</div>
<div>sdsd [[gammaValue]]</div>
</template>
<script>
class OsTestElement extends Polymer.Element {
static get is() {
return 'os-test';
}
static get properties() {
return {
alphaValue: {
type: Number,
value: 0.0
},
betaValue: {
type: Number,
value: 0.0
},
gammaValue: {
type: Number,
value: 0.0
}
};
}
connectedCallback() {
super.connectedCallback();
if (window.DeviceOrientationEvent) {
console.log("The browser support device orientation..")
window.addEventListener('deviceorientation', this.getSensorData.bind(this), true);
} else {
console.log("The browser doesn't support device orientation..");
}
}
disconnectedCallback() {
super.disconnectedCallback();
window.removeEventListener('deviceorientation', this.getSensorData.bind(this), true);
}
getSensorData(event) {
this.alphaValue = event.alpha;
this.betaValue = event.beta;
this.gammaValue = event.gamma;
}
}
window.customElements.define(OsTestElement.is, OsTestElement);
</script>
</dom-module>

Related

Stimulus event.params or destructs aren't returning the passed value

According to the documentation, we would pass a value to a method as parameters in the following way:
<div data-controller="item spinner">
<button data-action="item#upvote spinner#start"
data-item-id-param="12345"
data-item-url-param="/votes"
data-item-payload-param='{"value":"1234567"}'
data-item-active-param="true">…</button>
</div>
And in the controller javascript file, we have a few options. To call event.params, or to destruct.
// ItemController
upvote(event) {
// { id: 12345, url: "/votes", active: true, payload: { value: 1234567 } }
console.log(event.params)
}
upvote({ params: { id, url } }) {
console.log(id) // 12345
console.log(url) // "/votes"
}
Now, here's my own code:
.position-relative.w-100{data: {controller: "content-block"}}
%button.btn.btn-outline-dark{type: "button",
data: {action: "click->content-block#setblock",
setblock_style_param: "H2",
content_block_target: "toolbarH2"}} H2
and in the Controller:
Method 1:
setblock(event) {
alert(event.params)
}
returns [object Object]
Method 2:
setblock({params: { style }}) {
alert(style)
}
returns undefined.
What am I doing wrong?

How mutate data in method computed?

I'm on Vue 3. I have an onclick method which is supposed to modify the value of my props which is a boolean, I have tried several ways, I manage to enter the computed method, but the value of my props does not change
I register my data
data() {
return {
showConsommationWindow: false
}
}
then I tried 3 ways to change the value but none of them worked.
The first :
<submit-button v-on:click="showConsommationWindow = true" />
the 2nd : (alert is executed but the data value don't change)
<submit-button v-on:click="showConsommation(true)"/>
methods: {
showConsommation(boolValue){
alert('false')
this.showConsommationWindow = boolValue;
}
}
The last :
<submit-button v-on:click="showConsommation"/>
methods: {
showConsommation(){
if (!this.showConsommationWindow) {
alert('false')
this.showConsommationWindow = true;
return
}
this.showConsommationWindow = false;
}
},
I really don't understand why my data can't mutate, thanks for your help.
If value comes from a props, it means the parent distributes a boolean to the component. So if you want to change the boolean value, you should probably do:
// in parent
<Component :booleanValue="myBoolean" #changeBooleanValueEvent="changeMyBoolean" />
...
data() {
return {
myBoolean: true
}
}
methods: {
changeMyBoolean(value) {
this.myBoolean = value
}
}
// in component
props: {
booleanValue: {
...
}
}
methods: {
showConsommation() {
this.$emit('changeBooleanValueEvent', false)
}
}

Handle paste event in vue2-editor

I'm using this text editor https://github.com/davidroyer/vue2-editor that is based on Quilljs
I want to handle the paste event so it pastes only the plain text without any format but seems in the documentation that paste is not a supported event by default.
Is there any way to add the paste event?
I've already tried using v-on:paste in the Editor and adding the Quill custom module Clipboard but haven't had any success.
As I didn't find a way of doing it with the library I did it with the DOM
onPaste() {
const x = document.getElementById("removePasteFormat");
console.log(x);
x.addEventListener("paste", (e) => {
e.stopPropagation();
e.preventDefault();
let text = e.clipboardData.getData("text/plain");
// access the clipboard using the api
if (document.queryCommandSupported("insertText")) {
document.execCommand("insertText", false, text);
} else {
document.execCommand("paste", false, text);
}
});
},
Added the id to the div containing the text editors like this:
<div id="removePasteFormat"> *<<Here goes the text editor component>>* </div>
And register the method on mounted()
mounted() {
this.onPaste();
},
I think it would be good to make a plugin.
I made it simple.
src/utils/vue2Plugin/clipboard.ts
import Delta from 'quill/node_modules/quill-delta';
import Clipboard from 'quill/modules/clipboard';
import { Quill } from 'vue2-editor';
export class CustomClipboardPlugin extends Clipboard {
public quill!: Quill;
public options: any = {};
constructor(quill: Quill) {
super(quill, {
matchers: [],
});
this.quill = quill;
this.quill.root.addEventListener('paste', this.onPaste.bind(this), true);
}
onPaste(event: ClipboardEvent) {
event.preventDefault();
event.stopPropagation();
const range = this.quill.getSelection(true);
if (range === null) return;
let _textHtml;
if (event.clipboardData?.getData('text/html')) {
_textHtml = event.clipboardData?.getData('text/html');
} else if (event.clipboardData?.getData('text/plain')) {
_textHtml = `<p>${event.clipboardData?.getData('text/plain')}</p>`;
}
if (_textHtml) {
const pastedDelta = this.quill.clipboard.convert(_textHtml);
const delta = new Delta()
.retain(range.index)
.delete(range.length)
.concat(pastedDelta);
this.quill.updateContents(delta, Quill.sources.USER);
this.quill.setSelection(delta.length() - range.length, 0, Quill.sources.SILENT);
}
}
}
vue file
<template>
...
<VueEditor
...
:custom-modules="customModulesForEditor"
...
/>
...
</template>
// script
import CustomClipboardPlugin fro 'src/utils/vue2Plugin/clipboard.ts';
...
data() {
return {
customModulesForEditor: [{ alias: 'clipboard', module: CustomClipboardPlugin }],
};
},
...
I was wondering the same and came up with the following solution.
1 - Use the :editorOptions option referenced here
<template>
VueEditor(:editorOptions="editorSettings")
</template>
2 - Fill with the module.clipboard module with the option described here
3 - You can then handle the paste with your personal function (applied after quill's matcher). I've written mine following this answer on github
<script>
data() {
return {
editorSettings: {
modules: {
clipboard: {
matchers: [[Node.ELEMENT_NODE, this.customQuillClipboardMatcher]]
}
}
}
}
},
methods: {
customQuillClipboardMatcher(node, delta) {
delta.ops = delta.ops.map((op) => {
return {
insert: op.insert
}
})
return delta
},
}
</script>

Angular 5 - Event emitter (Property 'update' does not exist on type ....)

I've got a component that I want to update when a person's name changes by emitting an event. My problem is the code doesn't compile because of an error. This is my code
ApplicationFormComponent
#Output() nameChange = new EventEmitter();
closeAccordion(isComplete: string, accordionToClose: string, accordion: NgbAccordion) {
if (accordionToClose === 'personal-details-panel') {
this.applicationStatusFlags.personalDetailsStatus = (isComplete === 'true');
this.nameChange.emit({ personId: this.personId });
}
}
ApplicationFormComponent.html
<name-display
[personId]="personId"
[placeHolderText]="'Hello'"
(nameChange)="update($event)">
</name-display>
NameDisplayComponent
import { Component, Input, OnChanges, SimpleChanges } from '#angular/core';
import { PersonService } from "../../../service/person.service";
#Component({
selector: 'name-display',
templateUrl: './NameDisplay.component.html',
providers: [PersonService]
})
export class NameDisplayComponent implements OnChanges {
constructor(private readonly personService: PersonService) { }
#Input() personId;
#Input() placeHolderText: string = "";
forename: string = "";
ngOnChanges(changes: SimpleChanges): void {
if (changes["personId"]) {
this.personService.getPersonDetails(this.personId).subscribe((res: IPersonDetails) => {
this.forename = res.forenames;
});
}
};
update(personId: number) {
alert("update name");
this.personService.getPersonDetails(personId).subscribe((res: IPersonDetails) => {
this.forename = res.forenames;
});
}
}
My problem is basically when I use angular cli with the command ng server --aot, it doesn't compile because of this error:
ERROR in src\app\component\ApplicationForm\ApplicationForm.component.html(42,9): : Property 'update' does not exist on type 'ApplicationFormComponent'.
I've written a similar component that uses an event emitter which doesn't have this problem, so I'm stuck with how to fix the error.
Any ideas?
It is because you are passing $event to method.
(nameChange)="update($event)"
But it accepts number.
update(personId: number) {
alert("update name");
}
Please change the method as below.
update(event:any) {
const personId = event as number
alert("update name");
}

Mithril.js multiple css class

I'm new at mithril.js. I have a div, I want to add class "invalid" if ctrl.invalid()==true, and "hidden" if ctrl.hidden()==true.
If I use m('div', {class: ctrl.invalid() ? 'invalid' : '', class: ctrl.hidden()? 'hidden' : ''}), they override each other.
I can use m('div', {class: [ctrl.invalid()?'invalid':'', ctrl.focused()?'focused':''].join(' ')}), and it'll work, but it looks messy.
Is there an elegant solution for this? Thanks.
I recommend you to use classnames - a simple utility for that. You can define your classes in a nice way and it will merge everything for you. In your case it will be:
const myMergedClasses = classNames({
invalid: ctrl.invalid(),
focused: ctrl.focused()
});
m('div', { class: myMergedClasses })
Beautiful?!
Very late to the game, but as an inspiration for others ending up here, I often do something like the following, just because it is:
simple to implement
easy to extend
easy to understand
view(): {
const classes =
`${ctrl.invalid() ? '.invalid' : ''}` +
`${ctrl.hidden()? '.hidden' : ''}`;
return m(`div${classes}`);
}
You can add a helper method to your Mithril component:
const myComponent = {
css() {
// Add some logic
return 'class1 class2';
},
view() {
return m('div', { class: this.css() });
},
};
Or to the controller:
const ctrl = {
css() {
// Add some logic
return 'class3';
},
};
const myComponent = {
view() {
return m('div', { class: ctrl.css() });
},
};
Choose whichever suits your case better.
You can also use the classnames utility, as suggested by Ross Khanas in his answer:
const myComponent = {
css() {
return classNames({
invalid: ctrl.invalid(),
focused: ctrl.focused(),
});
},
view() {
return m('div', { class: this.css() });
},
};
Or:
const ctrl = {
css() {
return classNames({
invalid: this.invalid(),
focused: this.focused(),
});
},
invalid() { /* ... */ },
focused() { /* ... */ },
};
const myComponent = {
view() {
return m('div', { class: ctrl.css() });
},
};