vue-chartjs and custom legend using generateLegend() - vue-chartjs

The generateLegend() wrapper does call the legendCallback defined in my Vue code but I'm lost to how to render the custom HTML in vue-chartjs. What do I do with htmlLegend as described in the vue-chartjs api docs like here.
Here is the line chart component I'm trying to render with a custom HTML object.
import { Line, mixins } from 'vue-chartjs'
const { reactiveProp } = mixins
export default {
extends: Line,
mixins: [reactiveProp],
props: ['chartData','options'],
data: () => ({
htmlLegend: null
}),
mounted () {
this.renderChart(this.chartData, this.options);
this.htmlLegend = this.generateLegend();
}
}
Here is my vue template
<template>
<div class="col-8">
<line-chart :chart-data="datacollection" :options="chartOptions"></line-chart>
</div>
</template>

Well, htmlLegend holds the markup of the generated legend... so you can just put it into your tag via v-html
<template>
<div class="col-8">
<div class="your-legend" v-html="htmlLegend" />
<line-chart :chart-data="datacollection" :options="chartOptions"></line-chart>
</div>
</template>

mounted() {
this.renderChart( this.chartData , this.options );
var legend = this.generateLegend();
this.$emit('sendLegend', legend)
}
and then in the vue file add a new div to show the legend and also listen to the event to get the legend data
<div class="line-legend" v-html="chartLegend"></div>
<line-chart #sendLegend="setLegend" :chart-data="datacollection" :options="chartOptions"></line-chart>
and also add this to the data
chartLegend: null,
and you also need a method
setLegend (html) {
this.chartLegend = html
},

Related

Pass event options to on:event directive

Is it possible to pass event options to a svelte on:* directive?
To register an event listener with options I currently use:
<script lang="ts">
import { onMount } from "svelte"
let root: HTMLElement
onMount(() => {
const touchHandlerOptions = {
passive: true,
}
root.addEventListener("touchstart", handleTouchStart, touchHandlerOptions)
})
</script>
<div bind:this={root} />
Wondering if this could be refactored to pass the options in an on:* directive directly?
There is no way to pass options directly, but you can use event-modifiers:
<div on:touchstart|passive={handleTouchStart}>
See docs

Vuetify Date picker issue on nuxt

I am using a date picker somewhat similar to this example
File: datepicker.vue
<template>
<v-menu
v-model="dateMenu"
:close-on-content-click="false"
:nudge-right="40"
:return-value.sync="dateValue"
transition="scale-transition"
offset-y
>
<template v-slot:activator="{ on }">
<v-text-field
:label="dateLabel"
prepend-icon="fa-calendar"
readonly
v-model="dateValue"
v-on="on"
clearable
></v-text-field>
</template>
<v-date-picker
locale="en-in"
v-model="dateValue"
no-title
#input="dateMenu = false"
>
<v-spacer></v-spacer>
<v-btn
text
color="primary"
#click="dateMenu = false"
>Cancel</v-btn>
<v-btn
text
color="primary"
#click="$refs.dialog.save(dateValue)"
>OK</v-btn>
</v-date-picker>
</v-menu>
</template>
<script>
export default {
props: ['dateLabel','dateModel'],
data() {
return {
dateMenu: false,
dateValue: this.dateModel,
};
},
watch: {
dateValue(){
$nuxt.$emit('update',this.dateValue);
}
},
};
</script>
File: projects-subform.vue
...
<DatePicker
dateLabel="Project Start Date"
:dateModel="project.start_date"
#update="(v) => (project.start_date = v)"/>
...
(I exported DatePicker as a component from the projects form. )
When I select the date from picker UI, the display text on the v-text-field does not reflect the selected date. Also, the model project.start_date does not seem to update after I select the date from my datepicker. It becomes very tricky to debug when event errors like this don't show up on the dev tools console.
First of all, it is not recommended to change the model passed in as a prop directly. We don't want any unwanted breaks in the parent component. Rely on events. Somehow even this style of passing also didn't work quite well for me.
I did some workaround like this. (I know it is a very dirty way). But for some reason $emit with input/update/change just fails to be detected in the parent component. I am very sure there's a better way of doing this. But for now, moving on with life. :-(
File: datepicker.vue
<template>
...
<v-date-picker
locale="en-in"
v-model="dateValue"
no-title
#input="dateMenu = false;"
#change="saveDate" //change here
>
</v-date-picker>
...
</template>
<script>
...
methods(){
saveDate(val){
this.dateValue = val;
//changed here...emitting a custom event.
$nuxt.$emit("datePicked",{
project_number:this.project_number,
selectedDate: selDateVal
});
this.$refs.dateMenu.save(selDateVal);
}
...
</script>
File: project-subform.vue
...
<script>
...
created:{
this.$nuxt.$on('datePicked',this.updateDate);
}
...
methods:{
updateDate(v){
//do my stuff
this.projects[v.project_number].startDate = v.selectedDate
}
}
</script>

How to include and use tinymce in a svelte component?

I want to include an external rtf component in my svelte app.
I tried adding tinymce using the cdn in template.htm and then creating the following svelte component. The editor renders, however I can't get data into or out of the editor.
<script>
import { onMount, tick } from 'svelte'
export let label = ''
export let value = ''
$: console.log('value', value)
onMount(() => {
tinymce.init({
selector: '#tiny',
})
})
</script>
<p>
<label class="w3-text-grey">{label}</label>
<textarea id="tiny" bind:value />
</p>
Super old but encountered this today and found a solution.
Solution:
<svelte:head>
<script src="https://cdn.tiny..."></script>
</svelte:head>
<script>
import {onMount} from 'svelte';
let getHTML;
let myHTML;
onMount(() => {
tinymce.init({
selector: '#tiny'
})
getHTML = () => {
myHTML = tinymce.get('tiny').getContent();
}
})
</script>
<textarea id="tiny" bind:value />
<!-- click to get html from the editor -->
<button on:click={getHTML}>Get HTML from TinyMCE</button>
<!-- html is printed here -->
{myHTML}
Explanation:
My initial thought was to bind per normal with
<textarea bind:value></textarea>
but that doesn't work I think because tinyMCE is doing complicated stuff in the background. Instead of adding the cdn reference in template.htm I used <svelte:head> so it only is loaded for this component. The function tinymce.get('...').getContent() must be called to get the contents of the editor, but it requires tinyMCE, so it must be called within the onMount. So I define a function getHTML within onMount. Now getHTML can be used anywhere to assign the contents of the editor to myHTML.
step one:
run this command on in your terminal
npm install #tinymce/tinymce-svelte
(reference for installation : https://www.tiny.cloud/docs/integrations/svelte/)
step two :
<script>
import { onMount } from 'svelte';
let myComponent;
let summary='';
onMount(async()=>{
const module=await import ('#tinymce/tinymce-svelte');
myComponent=module.default;
})
</script>
step three :
<svelte:component this={myComponent} bind:value={summary}/>
{#html summary}

react-google-maps StandaloneSearchBox set specific country restriction?

I am trying to set a specific country restriction using react-google-maps StandaloneSearchBox.
I have tried componentRestrictions, but I'm not sure how to use it.
Sharing my code below:
export const AutoCompleteSearchBox = compose(
withProps({
googleMapURL:googleMapUrl,
loadingElement: <div style={{ height: `100%` }} />,
containerElement: <div style={{ height: `400px`, top:'3px' }} />,
}),
lifecycle({
componentWillMount() {
const refs = {}
this.setState({
types: ['(regions)'],
componentRestrictions: {country: "bd"},
onSearchBoxMounted:ref =>{ refs.searchBox = ref; },
onPlacesChanged:()=>{
const places = refs.searchBox.getPlaces();
this.props.onPlacesChanged(places);
},
})
const options = {
types: ['(regions)'],
componentRestrictions:{ country: 'bd' }
}
},
}),
withScriptjs
)`(props =>
<div data-standalone-searchbox="">
<StandaloneSearchBox
ref={props.onSearchBoxMounted}
bounds={props.bounds}
onPlacesChanged={props.onPlacesChanged}
controlPosition={ window.google.maps.ControlPosition.TOP_LEFT}
>
<TextField
className={props.inputClass}
placeholder={props.inputPlaceholder}
label={props.inputLabel}
name={props.inputName}
value={props.inputValue}
onChange={props.inputOnChange}
helperText={props.inputHelperText}
error={props.inputError}
/>
</StandaloneSearchBox>
</div>
);`
How can I solve this problem?
You can't add such restrictions for the SearchBox results, but you can specify the area towards which to bias query predictions. Predictions are biased towards, but not restricted to, queries targeting these bounds.
If you want to show only specific places, then you can Google Place Autocomplete feature. For it you don't event need to use additional React libraries for Google Maps. Here's the example:
import React, { Component } from 'react';
import Script from 'react-load-script'
class LocationMap extends Component {
handleScriptLoad() {
const inputEl = document.getElementById('address-input');
/*global google*/
var options = {
//types: ['address'],
componentRestrictions: {country: 'by'}
};
this.autocomplete = new google.maps.places.Autocomplete(inputEl, options);
this.autocomplete.addListener('place_changed', this.handlePlaceSelect.bind(this));
}
handlePlaceSelect() {
console.log(this.autocomplete.getPlace());
}
render() {
return (
<section>
<Script
url="https://maps.googleapis.com/maps/api/js?key=API_KEY&v=3.33&libraries=places&language=en&region=US"
onLoad={this.handleScriptLoad.bind(this)}
/>
<div className="form-group">
<label htmlFor="address-map">Enter address</label>
<input type="text"
autoComplete="new-password"
className="form-control"
id="address-input"
name="address"/>
</div>
</section>
);
}
}
export default LocationMap;
Don't forget to add react-load-script package: npm i react-load-script --save

KendoUI: Unable to bind data to HTML elements from JSON file.

I am new to kendo ui and mvvm, and I'm facing this issue:
I'm having a JSON file in the follow format:
[
{
"Id":1,
"img":"shoes.png"},
{"Id":2,
"img":"books.png"}
}
]
I am reading the file using the sample mentioned online by kendo guys as follows:
var crudServiceBaseUrl = "pro.json";
var viewModel = kendo.observable({
productsSource: new kendo.data.DataSource({
transport: {
read: {
url: crudServiceBaseUrl,
dataType: "json"
},
update: {
url: crudServiceBaseUrl,
dataType: "json"
},
destroy: {
url: crudServiceBaseUrl,
dataType: "json"
},
parameterMap: function(options, operation) {
if (operation !== "read" && options.models) {
return {
models: kendo.stringify(options.models)
};
}
return options;
}
},
batch: true,
schema: {
model: {
id: "Id"
}
}
})
});
kendo.bind($("#form-container"), viewModel);
I am able to bind the data from the data source to a Kendo Control such as a dropdownlist or some other Kendo Control. But when I try binding the data to an HTML Control (mostly an img tag). It stops working and gives an error saying "this.parent" is not a function.
following is the HTML which works:
Select Product: <select data-role="dropdownlist" data-value-field="Id" data-text-field="img"
data-bind="source: productsSource"></select>
However binding to a normal <img> tag does not work. In short I need to bind images based on src value to a div using kendo ui mvvm.
Kindly help me out. Thanks!!
-
Hardik
Currently Kendo MVVM cannot bind a data source to an HTML element. Only Kendo UI widgets can be bound to a kendo.data.DataSource. Using a widget e.g. the ListView would work for a DIV:
<div data-role="listview"
data-template="template"
data-bind="source: productsSource">
</div>
<script id="template" type="text/x-kendo-template">
<img data-bind="attr: { src: img }" />
</script>