VUEJS and CKEditor: Customize toolbar in VueJS - vuejs2

I have VUEJS app and I use CKEditor, I want to add color buttons on the toolbar, but it is not working.
import CKEditor from '#ckeditor/ckeditor5-vue';
Vue.use(CKEditor);
<ckeditor :editor="editor" :config="editorConfig"></ckeditor>
editor: ClassicEditor,
editorData: "<p>Content of the editor.</p>",
editorConfig: {
toolbarGroups: [
{ name: "document", groups: ["mode", "document", "doctools"] },
{ name: "clipboard", groups: ["clipboard", "undo"] },
{
name: "editing",
groups: ["find", "selection", "spellchecker", "editing"]
},
{ name: "forms", groups: ["forms"] },
"/",
{ name: "basicstyles", groups: ["basicstyles", "cleanup"] },
{
name: "paragraph",
groups: ["list", "indent", "blocks", "align", "bidi", "paragraph"]
},
{ name: "links", groups: ["links"] },
{ name: "insert", groups: ["insert"] },
"/",
{ name: "styles", groups: ["styles"] },
{ name: "colors", groups: ["colors"] },
{ name: "tools", groups: ["tools"] },
{ name: "others", groups: ["others"] },
{ name: "about", groups: ["about"] }
]
},
But in the final, I have got a toolbar that does not have the buttons that I put.

Related

vue route mapping with redirects

I hope this is a quick one.
I have this mapping that looks like this:
const routes = routeOptions.map((route) => {
return {
children: route?.children?.map((child) => {
return {
...{
path: child.path,
name: child.name,
meta: child.meta,
alias: child.alias,
},
component: () =>
import(
/* webpackPrefetch: true */
/* webpackChunkName: "[request]" */
`../views/${child.name
.replace(" ", "-")
.toLowerCase()}/${child.name
.replace(" ", "-")
.toLowerCase()}.component.vue`
),
};
}),
...{
path: route.path,
name: route.name,
meta: route.meta,
redirect: route.redirect,
},
component: () =>
import(
/* webpackChunkName: "[request]" */
`../views/${route.name
.replace(" ", "-")
.toLowerCase()}/${route.name
.replace(" ", "-")
.toLowerCase()}.component.vue`
),
};
});
Then I can set my routeOptions like this:
const routeOptions: RouteOptions[] = [{
path: "/account",
name: "account",
meta: {
title: "Account",
},
redirect: {
name: "sign-in",
},
children: [{
path: "sign-in",
name: "sign-in",
meta: {
title: "Sign in",
},
},
{
path: "join",
name: "join",
meta: {
title: "Join",
},
},
{
path: "add-password",
name: "add-password",
meta: {
title: "Add password",
},
},
{
path: "forgot-password",
name: "forgot-password",
meta: {
title: "Forgot password",
},
},
{
path: "reset-password",
name: "reset-password",
meta: {
title: "Reset password",
},
},
],
},
{
path: "/crew",
name: "staff",
meta: {
title: "Crew",
},
redirect: {
name: "staff-account",
},
children: [{
path: "account",
name: "staff-account",
meta: {
title: "Account",
authorize: ["Venue Staff", "Venue Manager"],
},
},
{
path: "demos",
name: "staff-demos",
meta: {
title: "Demos",
authorize: ["Venue Staff", "Venue Manager"],
},
},
{
path: "leader-boards",
name: "staff-leader-boards",
meta: {
title: "Leader boards",
authorize: ["Venue Staff", "Venue Manager"],
},
},
{
path: "search",
name: "staff-search",
meta: {
title: "Search",
authorize: ["Venue Staff", "Venue Manager"],
},
},
{
path: "stories",
name: "staff-stories",
meta: {
title: "Stories",
authorize: ["Venue Staff", "Venue Manager"],
},
},
],
},
{
path: "/404",
name: "not-found",
meta: {
title: "Page not found",
},
},
{
path: "*",
name: "layout",
meta: {},
children: [{
path: "/business/live-better",
name: "blog",
meta: {
title: "Partner Blog",
},
children: [{
path: ":title",
name: "blog",
}, ],
},
{
path: "/business/live-better/:title",
name: "blog-post",
},
{
path: "/brands",
name: "brand-list",
meta: {
title: "Brands",
},
},
{
path: "/brands/:brandSlug",
name: "brand-details",
meta: {
title: "Details",
},
},
{
path: "/categories",
redirect: {
name: "categories"
},
},
{
path: "/categories/:categorySlug",
redirect: {
name: "product-list"
},
},
{
path: "/categories/:categorySlug/:productId/:productTitle",
redirect: {
name: "product-details"
},
},
{
path: "/products",
name: "categories",
meta: {
title: "Products",
},
},
{
path: "/products/:categorySlug",
name: "product-list",
meta: {
title: "Products",
},
},
{
path: "/products/:categorySlug/:productId/:productTitle",
name: "product-details",
meta: {
title: "Details",
},
},
{
path: "/favourites",
name: "favourites",
meta: {
title: "Your favourites",
},
},
{
path: "/feedback",
name: "consumer-feedback",
meta: {
title: "Your feedback",
authorize: [],
},
},
{
path: "/venues/:venueSlug/theatres",
name: "theatre-list",
meta: {
title: "Theatres",
},
},
{
path: "/venues/:venueSlug/theatres/:theatreSlug",
name: "theatre-details",
meta: {
title: "Theatre",
},
},
{
path: "/venues",
name: "venue-list",
meta: {
title: "Venues",
},
},
{
path: "/venues/:venueSlug",
name: "venue-details",
meta: {
title: "Details",
},
},
{
path: "/search",
name: "search",
meta: {
title: "Search results",
},
},
{
path: "*",
name: "home",
meta: {
title: "Home",
},
},
],
},
];
Most of these work, but if you take a look at this section here:
{
path: "/categories",
redirect: { name: "categories" },
},
{
path: "/categories/:categorySlug",
redirect: { name: "product-list" },
},
{
path: "/categories/:categorySlug/:productId/:productTitle",
redirect: { name: "product-details" },
},
I want these to redirect to other named views.
The way my mapping works at the moment, is that it takes the name and looks in the views folder for a matching template, but these routes don't have templates because they are just redirects.
Does anyone know what I can do to my code to get it to work with these?
I did it like this:
const createChildRoutes = (children) => {
return children?.map((child) => {
const childRoute = {
path: child.path,
name: child.name,
meta: child.meta,
alias: child.alias,
redirect: child.redirect,
};
if (child.name) {
return {
...childRoute,
component: () =>
import(
/* webpackPrefetch: true */
/* webpackChunkName: "[request]" */ `../views/${child.name
.replace(" ", "-")
.toLowerCase()}/${child.name
.replace(" ", "-")
.toLowerCase()}.component.vue`
),
};
} else {
return childRoute;
}
});
};
const routes = routeOptions.map((route) => {
const mainRoute = {
path: route.path,
name: route.name,
meta: route.meta,
alias: route.alias,
redirect: route.redirect,
};
if (route.name) {
return {
children: createChildRoutes(route?.children),
...mainRoute,
component: () =>
import(
/* webpackPrefetch: true */
/* webpackChunkName: "[request]" */ `../views/${route.name
.replace(" ", "-")
.toLowerCase()}/${route.name
.replace(" ", "-")
.toLowerCase()}.component.vue`
),
};
} else {
return {
children: createChildRoutes(route?.children),
...mainRoute,
};
}
});

how to pass i18n data $t as prop to a component

in a normal way with out translation but i want to translate the two object array and bind into a component
<InfoNews
v-for="infonew in infonews"
:id="infonew.id"
:title="infonew.title"
:content="infonew.content"
/>
data() {
return {
infonews: [
{
id: "01",
title: "what we do",
content:"industke aecimen book. ",
},
{
id: "02",
title: "our mission",
content:"ggdddg",
},
],
};
Make infonews a computed property. The title and content of each should be the translation keys.
export default {
computed: {
infonews() {
return [
{
id: "01",
title: this.$t("what we do"),
content: this.$t("industke aecimen book"),
},
{
id: "02",
title: this.$t("our mission"),
content: this.$t("ggdddg"),
},
]
};
}
}

Vue-multiselect update field using AJAX

Here is my Vue multiselect component:
<multiselect v-model="selectedcategoryitem"
:options="options"
:multiple="true"
:internal-search="false"
group-values="libs"
group-label="category"
:group-select="true"
placeholder="Type to search"
track-by="value"
label="name"
v-on:select="toggleSelected">
<span slot="noResult">Oops! No elements found. Consider changing the search query.</span>
</multiselect>
And data and method:
data: { selectGoalID: 0
, selectedcategoryitem: []
, queryData: []
, options: [
{
value: 1,
category: 'item1',
libs: [
{ value: "1_1", name: 'name1(E)' },
{ value: "1_2", name: 'name2(P)' },
{ value: "1_3", name: 'name3(T)' },
{ value: "1_4", name: 'name4(F)' },
{ value: "1_5", name: 'name5' },
]
},
{
value: 2,
category: 'item2',
libs: [
{ value: "2_1", name: 'name1' },
{ value: "2_2", name: 'name2' }
]
},
{
value: 3,
category: 'item3',
libs: [
{ value: "3_1", name: 'name1' },
{ value: "3_2", name: 'name2' },
{ value: "3_3", name: 'name3' },
{ value: "3_4", name: 'name4' },
{ value: "3_5", name: 'name5' },
]
},
}
, methods: {
UpdateType: function (goal_id, selectedTypes) {
return $.ajax({
method: "POST"
, url: "#Url.Action("UpdateType", "Predict")"
, data: {
_goal_id: goal_id,
_selectedTypes: selectedTypes
}
, success: function (result) {
if (result.code == "S") {
}
else {
alertResultModel(result);
}
},
error: function (xhr, ajaxOptions, thrownError) {
alertInfo(xhr.statusText);
}
});
}
, toggleSelected: function (value) {
if (value.length > 0) {
this.queryData = JSON.parse(JSON.stringify(value));
}
console.log(this.queryData);
this.UpdateType(this.selectGoalID, this.queryData).then(
function (result) {
if (result.code == "S") {
}
else {
alertResultModel(result);
}
}
, function () {
alertError("Error!!");
}
);
}
}
And when I selected single item, console log return: null,
When i selected multiple items console log return:
(2) [{…}, {…}, __ob__: Observer]
0: {__ob__: Observer}
1: {__ob__: Observer}
length: 2
__ob__: Observer {value: Array(2), dep: Dep, vmCount: 0}
[[Prototype]]: Array
Question is:
Why first selected item is null, but v-model="selectedcategoryitem" selectedcategoryitem.length is 1.
How to convert value to JSON format send to Backend.
Step 1: Create an HTML template
<div id="app">
<multiselect
v-model="selectedcategoryitem"
:options="options"
:multiple="true"
:internal-search="false"
group-values="libs"
group-label="category"
:group-select="true"
placeholder="Type to search"
track-by="value"
label="name"
#input="onChange"
>
</multiselect>
<p>Selected Item: {{ selectedcategoryitem }}</p>
</div>
Step 2: Model data like,
data() {
return {
selectGoalID: 0,
selectedcategoryitem: [],
options: [
{
value: 1,
category: "item1",
libs: [
{ value: "1_1", name: "name1(E)" },
{ value: "1_2", name: "name2(P)" },
{ value: "1_3", name: "name3(T)" },
{ value: "1_4", name: "name4(F)" },
{ value: "1_5", name: "name5" },
],
},
{
value: 2,
category: "item2",
libs: [
{ value: "2_1", name: "name1" },
{ value: "2_2", name: "name2" },
],
},
{
value: 3,
category: "item3",
libs: [
{ value: "3_1", name: "name1" },
{ value: "3_2", name: "name2" },
{ value: "3_3", name: "name3" },
{ value: "3_4", name: "name4" },
{ value: "3_5", name: "name5" },
],
},
],
};
},
Step 3: Create an methods and call REST API call
methods: {
UpdateType: function (goal_id, selectedTypes) {
console.log("selectedTypes", selectedTypes);
return $.ajax({
method: "POST",
url: "#Url.Action('UpdateType', 'Predict')",
data: {
_goal_id: goal_id,
_selectedTypes: JSON.stringify(selectedTypes),
},
success: function (result) {
alert(result);
},
error: function (xhr, ajaxOptions, thrownError) {
alert(xhr.statusText);
},
});
},
onChange() {
console.log("this.selectedcategoryitem", this.selectedcategoryitem);
this.UpdateType(this.selectGoalID, this.selectedcategoryitem).then(
function (result) {
alert(result);
},
function () {
alert("Error!!");
}
);
},
},
You can see the logs for selected items and AJAX call form data
DEMO Link

Vue named views with lazy loading

I am trying to create my routes, but I want them to all use the default router-view in my app.
Looking at the documentation:
https://router.vuejs.org/guide/essentials/named-views.html
I should be able to target views by doing something like this:
const routes = [
{
path: "/",
name: "home",
component: {
default: Home
},
},
]
I want to do this with a child, so I did this:
{
path: "/categories",
name: "categories",
meta: {
title: "Categories",
},
component: Categories,
children: [
{
path: ":slug",
name: "product-list",
meta: {
title: "Categories",
},
component: { default: ProductList },
],
},
],
},
I get no compile errors, but when navigating to /categories/televisions it only shows the Categories component, not the ProductList.
So my first question is, can children target app level router-view?
I also tried to add a new router-view like this:
<router-view />
<router-view name="root" />
and then updated my routes to this:
{
path: "/categories",
name: "categories",
meta: {
title: "Categories",
},
component: Categories,
children: [
{
path: ":slug",
name: "product-list",
meta: {
title: "Categories",
},
component: { root: ProductList },
},
],
},
But this didn't work either.
If it is possible to do this, then my next question, which is where I am heading.
Can I use lazy loaded components and target named/default router-views?
For example, I have this function:
const lazyLoad = (name) => {
return () => import(`../views/${name}/${name}.component.vue`);
};
Which I call from my routes like this:
{
path: "/categories",
name: "categories",
meta: {
title: "Categories",
},
component: lazyLoad("categories"),
children: [
{
path: ":slug",
name: "product-list",
meta: {
title: "Categories",
},
component: lazyLoad("product-list"),
},
],
},
Can I do it like this?
{
path: "/categories",
name: "categories",
meta: {
title: "Categories",
},
component: lazyLoad("categories"),
children: [
{
path: ":slug",
name: "product-list",
meta: {
title: "Categories",
},
component: { default: lazyLoad("product-list") },
},
],
},
and target the root router-view?

How to implement Groupping in Nativescript Vue RadDataForm?

Want to use Fields grouping Documention is not prvided event the topic of grouping nor the example. Most of the example are using typescript. Event the Google is not showing the result.
<RadDataForm
ref="dataform"
:source="customerForm"
:metadata="customerFormMetadata"
:groups="groups"
/>
customerFormMetadata: {
isReadOnly: false,
commitMode: "Immediate",
validationMode: "Immediate",
propertyAnnotations: [
{
name: "customer_name_1",
displayName: "Customer Name",
index: 0,
groupName: "Personal",
editor: "Text"
},
groups: [
Object.assign(new PropertyGroup(), {
name: "Personal",
collapsible: true,
collapsed: false
}),
Object.assign(new PropertyGroup(), {
name: "Address",
collapsible: true,
collapsed: true
})
],
Grouping doesn't require any addtional configuration while using with Vue, it's pretty straight forward as described in the core docs.
Example
<template>
<Page class="page">
<ActionBar title="Home" class="action-bar" />
<RadDataForm :source="person" :metadata="groupMetaData" />
</Page>
</template>
<script>
import Vue from "nativescript-vue";
import RadDataForm from "nativescript-ui-dataform/vue";
Vue.use(RadDataForm);
export default {
data() {
return {
person: {
name: "John",
age: 23,
email: "john#company.com",
city: "New York",
street: "5th Avenue",
streetNumber: 11
},
groupMetaData: {
propertyAnnotations: [{
name: "city",
index: 3,
groupName: "Address",
editor: "Picker",
valuesProvider: [
"New York",
"Washington",
"Los Angeles"
]
},
{
name: "street",
index: 4,
groupName: "Address"
},
{
name: "streetNumber",
index: 5,
editor: "Number",
groupName: "Address"
},
{
name: "age",
index: 1,
editor: "Number",
groupName: "Main Info"
},
{
name: "email",
index: 2,
editor: "Email",
groupName: "Main Info"
},
{
name: "name",
index: 0,
groupName: "Main Info"
}
]
}
};
}
};
</script>
Edit:
As discussed in the docs, to make the Group collapsible use the groupUpdate event.
onGroupUpdate: function(args) {
let nativeGroup = args.group;
if (args.ios) {
nativeGroup.collapsible = true;
} else {
nativeGroup.setExpandable(true);
}
}
Updated Playground