How can a MenuItem be separated into its own module in Electron? - menu

New to Electron and building menus I'm trying to see if I can separate a MenuItem to prevent an enormous file but I'm having issues. For example I've separated the menu code outside of main.js and I moved menu in a renderer directory within a Menu directory. I can call the Menu from main.js with:
let mainMenu = Menu.buildFromTemplate(require('./renderer/Menus/mainMenu'))
mainMenu.js:
module.exports = [
{
label: 'Foo',
id: 'itemFoo',
submenu: [
{label: 'Enter Foo'},
{label: 'Exit Foo'}
]
},
{
label: 'Bar',
id: 'itemBar',
submenu: [
{label: 'Enter Bar'},
{label: 'Exit Bar'}
]
}
]
and it works but could each menu item be separated further into their own file and what would be the proper way to do that?
I've tried to take mainMenu.js and code it as:
const foo = require('./itemFoo')
module.exports = [
{foo},
{
label: 'Bar',
id: 'itemBar',
submenu: [
{label: 'Enter Bar'},
{label: 'Exit Bar'}
]
}
]
itemFoo.js:
module.exports = [
{
label: 'Foo',
id: 'itemFoo',
submenu: [
{label: 'Enter Foo'},
{label: 'Exit Foo'}
]
}
]
but I get an error:
TypeError: Invalid template for MenuItem: must have at least one of
label, role or type
Can a menu item in Electron be isolated into it's own module and if so how to do it? I didn't see this mentioned when searching [electron] menuitem or under the documentation

I figured out what I was doing wrong. I was writing the Menu Items incorrectly. It should be:
main.js:
const { Menu } = require('electron')
let mainMenu = Menu.buildFromTemplate(require('./renderer/Menus/mainMenu'))
app.on('ready', () => {
mainWindow.createWindow(),
Menu.setApplicationMenu(mainMenu)
})
mainMenu.js:
const foo = require('./itemFoo')
const bar = require('./itemBar')
module.exports = [
foo,
bar
]
itemBar.js:
module.exports = {
label: 'Foo',
id: 'itemFoo',
submenu: [
{label: 'Enter Foo'},
{label: 'Exit Foo'}
]
}
itemFoo.js:
module.exports = {
label: 'Bar',
id: 'itemBar',
submenu: [
{label: 'Enter Bar'},
{label: 'Exit Bar'}
]
}
That will allow me to have each main menu item in its own file and clear main.js.

This should work (untested though):
main process:
let mainMenuTemplate =
[
require('./renderer/Menus/itemFoo'),
require('./renderer/Menus/itemBar')
];
let mainMenu = Menu.buildFromTemplate(mainMenuTemplate);
itemFoo.js:
module.exports =
{
label: 'Foo',
id: 'itemFoo',
submenu: [
{label: 'Enter Foo'},
{label: 'Exit Foo'}
]
};
itemBar.js:
module.exports =
{
label: 'Bar',
id: 'itemBar',
submenu: [
{label: 'Enter Bar'},
{label: 'Exit Bar'}
]
};
Note: an intermediate mainMenu.js file is probably unnecessary then...

Related

Netlify CMS not saving hidden fields

Issue
I am using Netlify and Gatsby, actually working with this template to learn these systems. I can see in the pre-made files that there are hidden widgets in the admin/config.yml file for the CMS:
I am attempting create a new page with some widgets in the CMS:
- file: "src/pages/sidebar/index.md"
label: "Sidebar"
name: "sidebar"
fields:
- {
label: "Template Key",
name: "templateKey",
widget: "hidden",
default: "sidebar-page",
}
- { label: Title, name: title, widget: string }
- { label: Subtitle, name: subtitle, widget: string }
- { label: Body, name: body, widget: markdown }
- { label: Sidebar Title, name: sidebartitle, widget: string }
- { label: Sidebar Content, name: sidebarcontent, widget: markdown }
The normal fields all appear in the CMS, and they all get saved to the appropriate .md file in the path that I specified. However, the hidden fields are not being saved. This is resulting in build failures because GraphQL is attempting to build a page that doesn't exist, since the hidden templateKey field is supposed to be directing it to the appropriate Gatsby component. This is only occurring for new pages that I am creating. If I remove the templateKey field from a page that came with the template, it will resave that hidden field when I update the page in the CMS.
I am using the netlify-cms-proxy-server, but even if I send the CMS updates to my remote repo, the hidden fields are not saved.
I only found a couple other references to things tangentially related, and those are from years ago, so I suspect that it's something that I am doing that's preventing these from saving for my new pages.
If I manually add the templateKey field into my sidebar page's .md file, Gatsby will compile and the page will render. I can then edit the page in the CMS, save new content to the .md file, and the templateKey field will remain. Saving a new version does not remove the templateKey field.
I have also created an Issue on the template's github repository to try and get some insight from those involved there.
Here is my gatsby-config, gatsby-node, and config.yml files as well, if those are helpful:
Netlify CMS Config
backend:
name: git-gateway
branch: main
commit_messages:
create: "Create {{collection}} “{{slug}}”"
update: "Update {{collection}} “{{slug}}”"
delete: "Delete {{collection}} “{{slug}}”"
uploadMedia: "[skip ci] Upload “{{path}}”"
deleteMedia: "[skip ci] Delete “{{path}}”"
local_backend: true
media_folder: static/img
public_folder: /img
collections:
- name: "blog"
label: "Blog"
folder: "src/pages/blog"
create: true
slug: "{{year}}-{{month}}-{{day}}-{{slug}}"
fields:
- {
label: "Template Key",
name: "templateKey",
widget: "hidden",
default: "blog-post",
}
- { label: "Title", name: "title", widget: "string" }
- { label: "Publish Date", name: "date", widget: "datetime" }
- { label: "Description", name: "description", widget: "text" }
- { label: "Featured Post", name: "featuredpost", widget: "boolean" }
- { label: "Featured Image", name: "featuredimage", widget: image }
- { label: "Body", name: "body", widget: "markdown" }
- { label: "Tags", name: "tags", widget: "list" }
- name: "pages"
label: "Pages"
files:
- file: "src/pages/index.md"
label: "Landing Page"
name: "index"
fields:
- {
label: "Template Key",
name: "templateKey",
widget: "hidden",
default: "index-page",
}
- { label: Title, name: title, widget: string }
- { label: Image, name: image, widget: image }
- { label: Heading, name: heading, widget: string }
- { label: Subheading, name: subheading, widget: string }
- {
label: Mainpitch,
name: mainpitch,
widget: object,
fields:
[
{ label: Title, name: title, widget: string },
{ label: Description, name: description, widget: text },
],
}
- { label: Description, name: description, widget: string }
- {
label: Intro,
name: intro,
widget: object,
fields:
[
{ label: Heading, name: heading, widget: string },
{ label: Description, name: description, widget: text },
{
label: Blurbs,
name: blurbs,
widget: list,
fields:
[
{ label: Image, name: image, widget: image },
{ label: Text, name: text, widget: text },
],
},
],
}
- {
label: Main,
name: main,
widget: object,
fields:
[
{ label: Heading, name: heading, widget: string },
{ label: Description, name: description, widget: text },
{
label: Image1,
name: image1,
widget: object,
fields:
[
{ label: Image, name: image, widget: image },
{ label: Alt, name: alt, widget: string },
],
},
{
label: Image2,
name: image2,
widget: object,
fields:
[
{ label: Image, name: image, widget: image },
{ label: Alt, name: alt, widget: string },
],
},
{
label: Image3,
name: image3,
widget: object,
fields:
[
{ label: Image, name: image, widget: image },
{ label: Alt, name: alt, widget: string },
],
},
],
}
- file: "src/pages/about/index.md"
label: "About"
name: "about"
fields:
- {
label: "Template Key",
name: "templateKey",
widget: "hidden",
default: "about-page",
}
- { label: "Title", name: "title", widget: "string" }
- { label: "Body", name: "body", widget: "markdown" }
- file: "src/pages/products/index.md"
label: "Products Page"
name: "products"
fields:
- {
label: "Template Key",
name: "templateKey",
widget: "hidden",
default: "product-page",
}
- { label: Title, name: title, widget: string }
- { label: Image, name: image, widget: image }
- { label: Heading, name: heading, widget: string }
- { label: Description, name: description, widget: string }
- {
label: Intro,
name: intro,
widget: object,
fields:
[
{ label: Heading, name: heading, widget: string },
{ label: Description, name: description, widget: text },
{
label: Blurbs,
name: blurbs,
widget: list,
fields:
[
{ label: Image, name: image, widget: image },
{ label: Text, name: text, widget: text },
],
},
],
}
- {
label: Main,
name: main,
widget: object,
fields:
[
{ label: Heading, name: heading, widget: string },
{ label: Description, name: description, widget: text },
{
label: Image1,
name: image1,
widget: object,
fields:
[
{ label: Image, name: image, widget: image },
{ label: Alt, name: alt, widget: string },
],
},
{
label: Image2,
name: image2,
widget: object,
fields:
[
{ label: Image, name: image, widget: image },
{ label: Alt, name: alt, widget: string },
],
},
{
label: Image3,
name: image3,
widget: object,
fields:
[
{ label: Image, name: image, widget: image },
{ label: Alt, name: alt, widget: string },
],
},
],
}
- {
label: Testimonials,
name: testimonials,
widget: list,
fields:
[
{ label: Quote, name: quote, widget: string },
{ label: Author, name: author, widget: string },
],
}
- { label: Full_image, name: full_image, widget: image }
- {
label: Pricing,
name: pricing,
widget: object,
fields:
[
{ label: Heading, name: heading, widget: string },
{ label: Description, name: description, widget: string },
{
label: Plans,
name: plans,
widget: list,
fields:
[
{ label: Plan, name: plan, widget: string },
{ label: Price, name: price, widget: string },
{
label: Description,
name: description,
widget: string,
},
{ label: Items, name: items, widget: list },
],
},
],
}
- file: "src/pages/sidebar/index.md"
label: "Sidebar"
name: "sidebar"
fields:
- {
label: "Template Key",
name: "templateKey",
widget: "hidden",
default: "sidebar-page",
}
- { label: Title, name: title, widget: string }
- { label: Subtitle, name: subtitle, widget: string }
- { label: Body, name: body, widget: markdown }
- { label: Sidebar Title, name: sidebartitle, widget: string }
- { label: Sidebar Content, name: sidebarcontent, widget: markdown }
Gatsby Config
module.exports = {
siteMetadata: {
title: "Gatsby + Netlify CMS Starter",
description:
"This repo contains an example business website that is built with Gatsby, and Netlify CMS.It follows the JAMstack architecture by using Git as a single source of truth, and Netlify for continuous deployment, and CDN distribution.",
},
plugins: [
"gatsby-plugin-react-helmet",
{
resolve: "gatsby-plugin-sass",
options: {
sassOptions: {
indentedSyntax: false,
},
},
},
{
// keep as first gatsby-source-filesystem plugin for gatsby image support
resolve: "gatsby-source-filesystem",
options: {
path: `${__dirname}/static/img`,
name: "uploads",
},
},
{
resolve: "gatsby-source-filesystem",
options: {
path: `${__dirname}/src/pages`,
name: "pages",
},
},
{
resolve: "gatsby-source-filesystem",
options: {
path: `${__dirname}/src/img`,
name: "images",
},
},
`gatsby-plugin-image`,
"gatsby-plugin-sharp",
"gatsby-transformer-sharp",
{
resolve: "gatsby-transformer-remark",
options: {
plugins: [
{
resolve: "gatsby-remark-relative-images",
options: {
name: "uploads",
},
},
{
resolve: "gatsby-remark-images",
options: {
// It's important to specify the maxWidth (in pixels) of
// the content container as this plugin uses this as the
// base for generating different widths of each image.
maxWidth: 2048,
},
},
{
resolve: "gatsby-remark-copy-linked-files",
options: {
destinationDir: "static",
},
},
],
},
},
{
resolve: "gatsby-plugin-netlify-cms",
options: {
modulePath: `${__dirname}/src/cms/cms.js`,
},
},
{
resolve: "gatsby-plugin-purgecss", // purges all unused/unreferenced css rules
options: {
develop: true, // Activates purging in npm run develop
purgeOnly: ["/style.scss"], // applies purging only on the bulma css file
},
}, // must be after other CSS plugins
"gatsby-plugin-netlify", // make sure to keep it last in the array
],
};
Gatsby Node
const _ = require('lodash')
const path = require('path')
const { createFilePath } = require('gatsby-source-filesystem')
const { fmImagesToRelative } = require('gatsby-remark-relative-images')
exports.createPages = ({ actions, graphql }) => {
const { createPage } = actions
return graphql(`
{
allMarkdownRemark(limit: 1000) {
edges {
node {
id
fields {
slug
}
frontmatter {
tags
templateKey
}
}
}
}
}
`).then((result) => {
if (result.errors) {
result.errors.forEach((e) => console.error(e.toString()))
return Promise.reject(result.errors)
}
const posts = result.data.allMarkdownRemark.edges
posts.forEach((edge) => {
const id = edge.node.id
createPage({
path: edge.node.fields.slug,
tags: edge.node.frontmatter.tags,
component: path.resolve(
`src/templates/${String(edge.node.frontmatter.templateKey)}.js`
),
// additional data can be passed via context
context: {
id,
},
})
})
// Tag pages:
let tags = []
// Iterate through each post, putting all found tags into `tags`
posts.forEach((edge) => {
if (_.get(edge, `node.frontmatter.tags`)) {
tags = tags.concat(edge.node.frontmatter.tags)
}
})
// Eliminate duplicate tags
tags = _.uniq(tags)
// Make tag pages
tags.forEach((tag) => {
const tagPath = `/tags/${_.kebabCase(tag)}/`
createPage({
path: tagPath,
component: path.resolve(`src/templates/tags.js`),
context: {
tag,
},
})
})
})
}
exports.onCreateNode = ({ node, actions, getNode }) => {
const { createNodeField } = actions
fmImagesToRelative(node) // convert image paths for gatsby images
if (node.internal.type === `MarkdownRemark`) {
const value = createFilePath({ node, getNode })
createNodeField({
name: `slug`,
node,
value,
})
}
}
https://www.netlifycms.org/docs/widgets/hidden/
The hidden widget is not supported for file collections at the moment

can't parse inline keyboard button: InlineKeyboardButton

I'm using this package and I've created languages array and I'm trying to show them as buttons in my message but I receive this error
Unhandled rejection Error: ETELEGRAM: 400 Bad Request: can't parse inline keyboard button: InlineKeyboardButton must be an Object
Code
var languages = [
'ENGLISH',
'CHINESE',
'FRENCH',
'GERMAN',
'DUTCH NL / BE',
'SCANDINAVIAN(NORDISH / DANISH / SWEDISH)',
'FINNISH / SUOMI',
'ITALIAN',
'HUNGARIAN',
'BALKAN',
'FILIPINO',
'SPANISH',
'RUSSIAN',
'ARABIC',
'TURKISH',
'SLOVAKIAN',
'ROUMANIAN',
'PORTUGUESE',
'HINDI / OURDOU / ENGLISH(PAKISTAN & INDIA)',
'HINID / ENGLISH(ONLY INDIA)',
'INDONESIAN',
'MALAYSIAN',
'ZIMBABWE',
'NIGERIA',
'Other'
];
var options = languages.map(
x => [{ text: x, callback_data: x }]
);
console.log(options);
const languagesButtons = {
parse_mode: "html",
reply_markup: JSON.stringify({
inline_keyboard: [
options,
]
})
};
console.log(languagesButtons);
bot.sendMessage(chatId, "What language do you speak?", languagesButtons);
Results
console.log(options);
[
[ { text: 'ENGLISH', callback_data: 'ENGLISH' } ],
[ { text: 'CHINESE', callback_data: 'CHINESE' } ],
[ { text: 'FRENCH', callback_data: 'FRENCH' } ],
[ { text: 'GERMAN', callback_data: 'GERMAN' } ],
[ { text: 'DUTCH NL / BE', callback_data: 'DUTCH NL / BE' } ],
[
{
text: 'SCANDINAVIAN(NORDISH / DANISH / SWEDISH)',
callback_data: 'SCANDINAVIAN(NORDISH / DANISH / SWEDISH)'
}
],
[ { text: 'FINNISH / SUOMI', callback_data: 'FINNISH / SUOMI' } ],
[ { text: 'ITALIAN', callback_data: 'ITALIAN' } ],
[ { text: 'HUNGARIAN', callback_data: 'HUNGARIAN' } ],
[ { text: 'BALKAN', callback_data: 'BALKAN' } ],
[ { text: 'FILIPINO', callback_data: 'FILIPINO' } ],
[ { text: 'SPANISH', callback_data: 'SPANISH' } ],
[ { text: 'RUSSIAN', callback_data: 'RUSSIAN' } ],
[ { text: 'ARABIC', callback_data: 'ARABIC' } ],
[ { text: 'TURKISH', callback_data: 'TURKISH' } ],
[ { text: 'SLOVAKIAN', callback_data: 'SLOVAKIAN' } ],
[ { text: 'ROUMANIAN', callback_data: 'ROUMANIAN' } ],
[ { text: 'PORTUGUESE', callback_data: 'PORTUGUESE' } ],
[
{
text: 'HINDI / OURDOU / ENGLISH(PAKISTAN & INDIA)',
callback_data: 'HINDI / OURDOU / ENGLISH(PAKISTAN & INDIA)'
}
],
[
{
text: 'HINID / ENGLISH(ONLY INDIA)',
callback_data: 'HINID / ENGLISH(ONLY INDIA)'
}
],
[ { text: 'INDONESIAN', callback_data: 'INDONESIAN' } ],
[ { text: 'MALAYSIAN', callback_data: 'MALAYSIAN' } ],
[ { text: 'ZIMBABWE', callback_data: 'ZIMBABWE' } ],
[ { text: 'NIGERIA', callback_data: 'NIGERIA' } ],
[ { text: 'Other', callback_data: 'Other' } ]
]
console.log(languagesButtons);
{
parse_mode: 'html',
reply_markup: '{"inline_keyboard":[[[{"text":"ENGLISH","callback_data":"ENGLISH"}],[{"text":"CHINESE","callback_data":"CHINESE"}],[{"text":"FRENCH","callback_data":"FRENCH"}],[{"text":"GERMAN","callback_data":"GERMAN"}],[{"text":"DUTCH NL / BE","callback_data":"DUTCH NL / BE"}],[{"text":"SCANDINAVIAN(NORDISH / DANISH / SWEDISH)","callback_data":"SCANDINAVIAN(NORDISH / DANISH / SWEDISH)"}],[{"text":"FINNISH / SUOMI","callback_data":"FINNISH / SUOMI"}],[{"text":"ITALIAN","callback_data":"ITALIAN"}],[{"text":"HUNGARIAN","callback_data":"HUNGARIAN"}],[{"text":"BALKAN","callback_data":"BALKAN"}],[{"text":"FILIPINO","callback_data":"FILIPINO"}],[{"text":"SPANISH","callback_data":"SPANISH"}],[{"text":"RUSSIAN","callback_data":"RUSSIAN"}],[{"text":"ARABIC","callback_data":"ARABIC"}],[{"text":"TURKISH","callback_data":"TURKISH"}],[{"text":"SLOVAKIAN","callback_data":"SLOVAKIAN"}],[{"text":"ROUMANIAN","callback_data":"ROUMANIAN"}],[{"text":"PORTUGUESE","callback_data":"PORTUGUESE"}],[{"text":"HINDI / OURDOU / ENGLISH(PAKISTAN & INDIA)","callback_data":"HINDI / OURDOU / ENGLISH(PAKISTAN & INDIA)"}],[{"text":"HINID / ENGLISH(ONLY INDIA)","callback_data":"HINID / ENGLISH(ONLY INDIA)"}],[{"text":"INDONESIAN","callback_data":"INDONESIAN"}],[{"text":"MALAYSIAN","callback_data":"MALAYSIAN"}],[{"text":"ZIMBABWE","callback_data":"ZIMBABWE"}],[{"text":"NIGERIA","callback_data":"NIGERIA"}],[{"text":"Other","callback_data":"Other"}]]]}'
}
Can you tell me what's wrong?
Update
Based on CherryDT answer I can get my buttons but:
I have other inline keyboard which works as expected here is sample of it:
const contactKeyboardTwo = {
parse_mode: "html",
reply_markup: JSON.stringify({
inline_keyboard: [
[{ text: 'Website', url: 'https://www.google.com' }],
[{ text: 'Chart', url: 'https://www.google.com' }],
[{ text: 'How to buy', url: 'https://www.google.com' }],
[{ text: 'Contract', url: 'https://www.google.com' }],
[{ text: 'Contract', url: 'https://www.google.com' }]
]
})
};
bot.sendMessage(chatId, "Welcome", contactKeyboardTwo);
result
Now new code return results like this
how can I have my languages list same as fist image?
The inline_keyboard array expects object of type InlineKeyboardButton like these (not the same library, but you can see the structure).
I can see you attempted to do that here:
var options = languages.map(
x => [{ text: x, callback_data: x }]
);
But the problem is, this maps each language to an array with one element with the object inside, so at the end you get an array of arrays:
[
[
{ text: 'AAA', callback_data: 'AAA' }
],
[
{ text: 'BBB', callback_data: 'BBB' }
]
]
So, the error says that the button object is not an InlineKeyboardObject object because it's actually an array and hence invalid.
What you need is this:
[
{ text: 'AAA', callback_data: 'AAA' },
{ text: 'BBB', callback_data: 'BBB' }
]
...which you'll get by removing the square brackets [ ] in your map callback (replacing them with ( ) instead because otherwise it would be parsed as block and not as object literal):
var options = languages.map(
x => ({ text: x, callback_data: x })
);
Fixed
All I needed to do was to remove [] from my inline_keyboard
var options = languages.map(
x => [{ text: x, callback_data: x }]
);
const languagesButtons = {
parse_mode: "html",
reply_markup: JSON.stringify({
inline_keyboard: options, // removed [] around option
})
};
In my case InlineKeyboardObject was missing one of the optional parameters

Mongoose schema infinite nesting

I'm having some trouble creating a model that describes the object that I want to store in mongoDB.
This is the object:
simple: [
{
label: 'Satisfied customers',
children: [
{
label: 'Good food',
children: [
{ label: 'Quality ingredients' },
{ label: 'Good recipe' }
]
},
{
label: 'Good service (disabled node)',
children: [
{ label: 'Prompt attention' },
{ label: 'Professional waiter' }
]
},
{
label: 'Pleasant surroundings',
children: [
{ label: 'Happy atmosphere' },
{ label: 'Good table presentation' },
{ label: 'Pleasing decor' }
]
}
]
}
]
This is data that is input to a QTree: https://quasar.dev/vue-components/tree
I want to model this but this object can in theory expand indefinitely as each child can have children of it's own and so on. Is there a way to do this nicely in a Mongoose Schema? My search so far turned up empty.
Here is what I have now:
simple: [{
_id: false,
label: String,
children: [{
_id: false,
label: String,
}]
}]
I can ofcourse choose to limit the depth to a certain amount (say 5) and put that amount of nesting in my schema, but I'm trying to find a more elegant solution so that I dont have to do that.

Electron - Update label in menu

I try to update label on menu item when I click this menu item. It should works like click->'show' label, click->'hide' label. This is my code:
const template = [{
label: 'Menu',
submenu: [{
label: 'Search',
click() {
win.webContents.executeJavaScript("showSearch()"); // it run function changeSearch() in main.js
}
},
{
label: 'Resetuj',
click() {
win.loadURL(`file://${__dirname}/index.html?del=1`);
}
},
{
label: 'Quit',
accelerator: 'Q+CmdOrCtrl+Q',
click() {
win.loadURL(`file://${__dirname}/index.html?logout=1&close=1`);
}
}]
}];
changeSearch() I tried something like this:
Menu.items[0].submenu.items[0].label = "Changed label";
I think what you are looking for is something like this:
function addMenuItems(items, position) {
const updateSearchItems = [{
label: 'newOptionDisabled',
enabled: false,
}, {
label: 'newOptionWithAction',
enabled: true,
key: 'newOptionWIthAction',
}, {
label: 'Do some stuff',
visible: false,
key: 'doSomeStuff',
click: () => {
// stuff
},
}];
items.splice.apply(items, [position, 0].concat(updateSearchItems));
}
By defining your menu items as an object that you can reference you can always modify the object later. In my example I use a addMenuItems function that enables me to specify where I want to insert these items within the existing object.
I did this to change/modify my menu item dynamically:
const menuTemplate = [{
label: 'Options',
submenu: [
{
label: 'Hide',
click() {
changeLabel('Show'); // Put logic here
}
}
]
}];
function changeLabel(label) {
menuTemplate[0].submenu[0].label = label;
// Rebuild menu
const menu = Menu.buildFromTemplate(menuTemplate);
Menu.setApplicationMenu(menu);
}
This code is not tested!

JointJS: Inspector doesn't edit link label?

I'm working on a Flowchart editor and I want the ui.inspector to edit labels on links.
I did the following:
function createInspector(cellView) {
if (!inspector || inspector.options.cellView !== cellView) {
if (inspector) {
inspector.remove();
}
inspector = new joint.ui.Inspector({
inputs: {
labels:
attrs: {
text:{
text: { type: 'textarea', group: 'Labels', label: 'Label', index: 2 },
}
}
},
},
},
groups: {
labels:[ { label: 'Labels', index: 1 },
}],
cellView: cellView
});
$('#inspector-holder-create').html(inspector.render().el);
}
}
paper.on('cell:pointerdown', function(cellView) {
createInspector(cellView);
});
However, when I edit a link it shows in the JSON output:
"labels": {
"0": {
"attrs": {
"text": {
"text": "Text I entered"
}
}
}
},
but doesn't actually render on the link in the stencil.
I think the problem is with the { "0": part the inspector adds. I want to remove that and replace with it [ ] so the output will be
labels: [
{ attrs: { text: { text: 'label' } } }
]
What should I do ??
It is possible to define Inspector inputs with paths.
'labels/0/attrs/text/text': {
type: 'text',
group: 'Text',
index: 1,
label: 'Label'
}
Or as a combination of attributes nesting and paths.
'labels/0/attrs': {
text: {
text: {
type: 'text',
group: 'Text',
index: 1,
label: 'Label'
},
fontSize: {
type: 'number',
group: 'Text',
index: 2,
label: 'Font Size'
}
}
}
This is valid for Rappid v2.4.0+.
inspector = new joint.ui.Inspector({
inputs: {
'labels': [
{attrs: {
text: {
text: {
type: 'text',
group: 'someGroup',
index: 1,
label: "Label"
}
}
}}
]
}});

Resources