I was trying to add a custom shortcode in the admin panel when my custom block added to the page.
( function( blocks, element, editor, components) {
var el = element.createElement;
const { RichText, InspectorControls, BlockEdit } = editor;
const { Fragment } = element;
const { TextControl, ToggleControl, Panel, PanelBody, PanelRow, SelectControl } = components;
blocks.registerBlockType( 'gutenberg-custom/show-information', {
title: 'Show information',
icon: 'universal-access-alt',
category: 'layout',
example: {},
attributes: {
exhibitor_id:{
type: "string"
}
},
edit: function(props) {
console.log('props', props)
return el(
Fragment,
{},
el(
InspectorControls,
{},
el(
PanelBody,
{ title: "Show Settings", initialOpen: true },
/* Text Field */
el(
PanelRow,
{},
el(SelectControl, {
label: "Select Exhibitor",
options: [
{ label: 'Big', value: '100%' },
{ label: 'Medium', value: '50%' },
{ label: 'Small', value: '25%' },
] ,
onChange: value => {
props.setAttributes({ exhibitor_id: value });
},
value: props.attributes.exhibitor_id
})
)
),
)
);
},
save: function(props){
return 'Test output'
}
} );
}(
window.wp.blocks,
window.wp.element,
window.wp.editor,
window.wp.components
) );
The above is my js code. I could add the settings for the block but I couldn't figure out how can I add my custom content that is '[custom-shortcode]' in the block itself (like in the picture).
How can I do that?
edit: function(props) {
console.log("props", props);
return el(
Fragment,
{},
el(
InspectorControls,
{},
el(
PanelBody,
{ title: "Show Settings", initialOpen: true },
el(
PanelRow,
{},
el(SelectControl, {
label: "Select Exhibitor",
options: [
{ label: "Big", value: "100%" },
{ label: "Medium", value: "50%" },
{ label: "Small", value: "25%" }
],
onChange: value => {
props.setAttributes({ exhibitor_id: value });
},
value: props.attributes.exhibitor_id
})
)
)
),
el(
"div",
{},
"[show-information]"
)
);
},
Related
I am trying to change the background color of the cell based on its value inside. I am currently using this library: react-data-table-component
Logic:
If value is greater than 0, then the background color of the cell will be red.
Otherwise there won't be a background color.
Here's my current snippet code for the Data Table:
const CountryTable = ({items}) => {
return(
<DataTable
title="Covid-19 Stats"
defaultSortAsc="false"
responsive
defaultSortField="cases"
defaultSortAsc={false}
striped
highlightOnHover
data={items}
columns={
[
{
name: '#',
selector: (row, index) => index+1,
disableSortBy: true,
},
{
name: 'Country',
selector: 'country',
sortable: true,
},
{
name: 'Total Cases',
selector: 'cases',
sortable: true,
},
{
getProps: (state, rowInfo) => {
if (rowInfo && rowInfo.row) {
return {
style: {
background:
parseInt(rowInfo.row.todayCases) > 0 ? "red" : null
}
};
} else {
return {};
}
},
name: 'Additional New Cases',
selector: 'todayCases',
sortable: true,
},
{
name: 'Current Active Cases',
selector: 'active',
sortable: true,
},
{
name: 'Total Deaths',
selector: 'deaths',
sortable: true,
},
{
name: 'Additional New Deaths',
selector: 'todayDeaths',
sortable: true,
},
{
name: 'Total Recoveries',
selector: 'recovered',
sortable: true,
},
{
name: 'Additional New Recoveries',
selector: 'todayRecovered',
sortable: true,
},
]
}
/>
);
}
And here's the illustration of what it should be look like:
The docs say you can set conditional styles like this: https://www.npmjs.com/package/react-data-table-component#conditional-style-object
const conditionalRowStyles = [
{
when: row => row.calories < 300,
style: {
backgroundColor: 'green',
color: 'white',
'&:hover': {
cursor: 'pointer',
},
},
},
// You can also pass a callback to style for additional customization
{
when: row => row.calories < 300,
style: row => ({
backgroundColor: row.isSpecia ? 'pink' : 'inerit',
}),
},
];
const MyTable = () => (
<DataTable
title="Desserts"
columns={columns}
data={data}
conditionalRowStyles={conditionalRowStyles}
/>
);
I quickly put together an example usings cell and styled components:
https://codesandbox.io/s/upbeat-galileo-r7p34?file=/src/App.js
import "./styles.css";
import DataTable from "react-data-table-component";
import styled from "styled-components";
const StyledCell = styled.div`
&.low {
background: green !important;
}
&.medium {
background: orange;
}
&.high {
background: red !important;
}
`;
export default function App() {
let items = [
{
Country: "Canada",
AdditionalNewCases: 500
},
{
Country: "England",
AdditionalNewCases: 5000
},
{
Country: "USA",
AdditionalNewCases: 500000
}
];
function getCssClass(value) {
if (value > 5000) return "high";
else if (value > 500) return "medium";
return "low";
}
return (
<DataTable
title="Covid-19 Stats"
defaultSortAsc="false"
responsive
defaultSortAsc={false}
striped
highlightOnHover
data={items}
columns={[
{
name: "number",
selector: (row, index) => index + 1,
disableSortBy: true
},
{
name: "Country",
selector: "Country",
sortable: true
},
{
name: "New Cases",
selector: "AdditionalNewCases",
sortable: true,
cell: (row) => (
<StyledCell className={getCssClass(row.AdditionalNewCases)}>
{row.AdditionalNewCases}
</StyledCell>
)
}
]}
/>
);
}
I am getting this error when I add a value to the buttonUrl input.
A component is changing an uncontrolled input of type url to be controlled. Input elements should not switch from uncontrolled to controlled (or vice versa). Decide between using a controlled or uncontrolled input element for the lifetime of the component.
this is the code for my block.
Also what do i need to change to get a span inside of my h3 subhead.
I have been going around for ages with this. Cheers
( function ( blocks, editor, i18n, element, components, _ ) {
const __ = i18n.__;
const el = element.createElement;
const RichText = editor.RichText;
const MediaUpload = editor.MediaUpload;
const InspectorControls = editor.InspectorControls;
const PanelBody = components.PanelBody;
const TextControl = components.TextControl;
const SelectControl = components.SelectControl;
blocks.registerBlockType('unify/about-block', {
title: __('Unify About Block', 'unify'),
icon: 'align-left',
category: 'layout',
attributes: {
title: {
type: 'array',
source: 'children',
selector: 'h2',
},
subhead: {
type: 'array',
source: 'children',
selector: 'h3',
},
content: {
type: 'string'
},
mediaID: {
type: 'number',
default: 0
},
mediaURL: {
type: 'string',
source: 'attribute',
selector: 'img',
attribute: 'src',
},
buttonText: {
type: 'string',
default: ''
},
buttonUrl: {
type: 'url',
default: ''
},
blockColor: {
type: 'string',
default: 'brand-dark-blue'
},
},
edit: function ( props ) {
const attributes = props.attributes;
const onSelectImage = function ( media ) {
return props.setAttributes({
mediaURL: media.url,
mediaID: media.id,
});
};
return el(
'div',
{
className: props.className
},
el(
'div',
{ className: 'column block-content' },
el(
RichText,
{
tagName: 'h2',
inline: true,
placeholder: __('Title', 'unify'),
value: attributes.title,
onChange: function ( value ) {
props.setAttributes({ title : value });
},
}
),
el(
RichText,
{
tagName: 'h3',
inline: true,
placeholder: __('Subhead', 'unify'),
value: attributes.subhead,
onChange: function ( value ) {
props.setAttributes({ subhead : value });
},
}
),
el(
RichText,
{
tagName: 'p',
placeholder: i18n.__('Content', 'unify'),
value: attributes.content,
onChange: function ( value ) {
props.setAttributes({ content : value });
}
}
),
el(
'a',
{
className: 'components-button button button-large is-primary',
href: attributes.buttonURL
},
attributes.buttonText
)
),
el(
'div',
{
className: 'column block-image'
},
el(
MediaUpload,
{
onSelect: onSelectImage, allowedTypes: 'image', value: attributes.mediaID,
render: function ( obj ) {
return el(
components.Button,
{
className: attributes.mediaID ? 'image-button' : 'button button-large', onClick: obj.open
},
! attributes.mediaID ? __('Upload Image', 'unify') : el('img', { src: attributes.mediaURL })
);
},
}
)
),
el(
InspectorControls,
{
key: 'inspector'
},
el(
PanelBody,
{ title: i18n.__('Button Link'), className: 'block-button-link', initialOpen: true },
el(
TextControl,
{
type: 'url',
label: i18n.__('Enter the destination URL for the button'),
value: props.attributes.buttonURL,
onChange: function ( newButtonURL ) {
console.log(newButtonURL);
props.setAttributes({ buttonURL: newButtonURL });
}
}
),
el(
TextControl,
{
type: 'text',
label: i18n.__('Button Text', 'unify'),
value: attributes.buttonText,
onChange: function (newButtonText) {
props.setAttributes({ buttonText: newButtonText })
}
}
)
),
el(
PanelBody,
{ title: i18n.__('Color Settings'), className: 'block-color', initialOpen: false },
el(
SelectControl,
{
type: 'string',
label: i18n.__('Choose the highlight color for the block'),
value: attributes.blockColor ? attributes.blockColor : '',
options: [{
label: 'Dark Blue',
value: 'brand-dark-blue'
},{
label: 'Light Blue',
value: 'brand-blue'
},{
label: 'Green',
value: 'brand-green'
},{
label: 'Purple',
value: 'brand-purple'
}],
onChange: function ( value ) {
props.setAttributes({ blockColor : value });
},
}
),
),
)
)
},
save: function ( props ) {
const attributes = props.attributes;
return el(
'section',
{
className: 'about-block-section ' + attributes.blockColor
},
el(
'div',
{
className: 'grid-container'
},
el(
'div',
{
className: 'grid-x grid-padding-x align-center-middle'
},
el(
'div',
{
className: 'cell small-12 medium-6 large-6 small-order-2 medium-order-1 about-block-image-outer'
},
el(
'div',
{
className: 'about-block-image square-aspect-ratio'
},
attributes.mediaURL ? el(
'img',
{
src: attributes.mediaURL
}
) : ''
),
),
el(
'div',
{
className: 'cell small-12 medium-6 large-5 large-offset-1 small-order-2 medium-order-1 about-block-content-outer'
},
attributes.title ? el(
RichText.Content,
{
tagName: 'h2',
className: 'about-block-content-title',
value: attributes.title,
}
) : '',
attributes.subhead ? el(
RichText.Content,
{
tagName: 'h3',
className: 'about-block-content-subhead',
value: attributes.subhead,
}
) : '',
attributes.content ? el(
RichText.Content,
{
tagName: 'p',
className: 'about-block-content-body',
value: attributes.content
}
) : '',
attributes.buttonURL && attributes.buttonText ? el(
'a',
{
href: attributes.buttonURL,
className: 'button about-block-content-button'
},
attributes.buttonText,
el(
'i',
{ className: 'fas fa-arrow-right'}
)
) : ''
)
)
)
)
},
});
} )(
window.wp.blocks,
window.wp.blockEditor,
window.wp.i18n,
window.wp.element,
window.wp.components,
window._
);
This is likely long after you've resolved this but I believe it'll help someone else. That issue is usually down to a component's value being set as undefined initially. See A component is changing an uncontrolled input of type text to be controlled error in ReactJS
From your error message:
A component is changing an uncontrolled input of type url to be controlled. Input elements should not switch from uncontrolled to controlled (or vice versa). Decide between using a controlled or uncontrolled input element for the lifetime of the component.
You have one component of type URL - TextControl and the value being passed to it is value: props.attributes.buttonURL
So based on that, I believe buttonURL is undefined at some point, which results in that error. To address that, set a default value for buttonURL in the edit.
edit: function ( props ) {
const attributes = props.attributes;
const buttonURL = props.attributes && props.attributes.buttonURL ?? props.attributes.buttonURL : '' // Decide on an appropriate default
const onSelectImage = function ( media ) {
return props.setAttributes({
mediaURL: media.url,
mediaID: media.id,
});
};
Then use it in the TextControl component - value: props.attributes.buttonURL becomes value: buttonURL
I can't display custom icons on the actions tab from ng2-smart-table. I have installed Eva Icons from Akevo Team and I want to use them. I have changed the edit button to show some custom icons but the problem is that nothing appears. On the left side of delete, a brush icon had to appear.
Here is an image with the problem:
Here is the code:
settings = {
edit: {
editButtonContent: '<nb-icon icon="brush"></nb-icon>',
saveButtonContent: '<nb-icon icon="checkmark"></nb-icon>',
cancelButtonContent: '<nb-icon icon="close-circle"></nb-icon>'
},
columns: {
device: {
title: 'Device',
sortDirection: 'asc'
},
type: {
title: 'Type',
sort: false,
filter: false
},
serialNumber: {
title: 'Serial Number'
},
status: {
title: 'Status'
}
}
};
Try this :
settings = {
hideSubHeader: true,
actions: {
custom: [
{
name: 'edit',
title: '<nb-icon icon="brush"></nb-icon>'
},
{
name: 'save',
title: '<nb-icon icon="checkmark"></nb-icon>'
},
{
name: 'cancel',
title: '<nb-icon icon="close-circle"></nb-icon>'
}
],
add: false,
edit: false,
delete: false
}
...
};
hope this works for you!
Also you can use other icons sets like material icons, just add it to your project and then change your settings like:
settings = {
edit: {
editButtonContent: '<span class="material-icons">mode_edit</span>',
saveButtonContent: '<span class="material-icons">check_circle</span>',
cancelButtonContent: '<span class="material-icons">cancel</span>'
},
/* ... */
}
settings = {
hideSubHeader: true,
sort: true,
actions: {
position: 'left',
add: false,
edit: false,
delete: false,
select: false,
custom: [
{
name: 'viewRecord',
type: 'html',
title: '<i class="far fa-file-alt" title="View Record"></i>',
},
{
name: 'editRecord',
type: 'html',
title: '<i class="far fa-edit" title="Edit Record"></i>',
},
],
},
columns: {
column1: {
title: 'Column 1',
type: 'string',
width: '35%',
},
column2: {
title: 'Column 2',
type: 'string',
},
column3: {
title: 'Column 3',
type: 'string',
},
},
};
I found this thread:
https://github.com/akveo/ng2-smart-table/issues/1034
And so as mentioned in the last comment:
temporarily use the old nebular-icons
https://github.com/akveo/nebular-icons/tree/master/src/icons
I downloaded the required icon's SVG and added them as:
settings = {
edit: {
editButtonContent: '<img src="assets/images/nb-edit.svg" width="40" height="40" >'
. . .
}
. . .
}
Works well enough.
let newSettings = {
mode: "external",
actions: {
add: false,
edit: false,
delete: false,
position: 'right'
},
hideSubHeader: true,
add: {
addButtonContent: '<i class="nb-plus"></i>',
},
edit: {
editButtonContent: '<img src="assets/images/icons/outline/settings-2-outline.svg" width="20" height="20" >',
},
delete: {
deleteButtonContent: '<img src="assets/images/icons/outline/trash-2-outline.svg" width="20" height="20" >',
confirmDelete: true,
},
}
How can you preselect a specific listbox option when your plugin dialog opens?
tinymce.PluginManager.add('mybutton', function(editor, url) {
editor.addButton('mybutton', {
icon: true,
image: url + '/img/mybutton.png',
title: 'Select An Option',
onclick: function() {
editor.windowManager.open({
title: 'My options',
body: [
{
type: 'listbox',
name: 'myoptions',
label: 'My Options',
'values': [
{text: 'Option 1', value: '1'},
{text: 'Option 2', value: '2'},
{text: 'Option 3', value: '3'}, /* preselect this option */
{text: 'Option 4', value: '4'},
{text: 'Option 5', value: '5'},
]
}
],
onsubmit: function(v) {
editor.insertContent(v.data.myoptions);
}
});
}
});
});
For some reason this is missing in the Listbox documentation but the solution is quite simple: Add a value property to the listbox object you pass to tinymce and it will preselect it.
Be careful to set the value not to the text/label but the actual value of the listbox item you want to preselect.
tinymce.PluginManager.add('mybutton', function(editor, url) {
editor.addButton('mybutton', {
icon: true,
image: url + '/img/mybutton.png',
title: 'Select An Option',
onclick: function() {
editor.windowManager.open({
title: 'My options',
body: [
{
type: 'listbox',
name: 'myoptions',
label: 'My Options',
values: [
{text: 'Option 1', value: '1'},
{text: 'Option 2', value: '2'},
{text: 'Option 3', value: '3'}, /* preselect this option */
{text: 'Option 4', value: '4'},
{text: 'Option 5', value: '5'},
],
value: '3'
}
],
onsubmit: function(v) {
editor.insertContent(v.data.myoptions);
}
});
}
});
});
I found it much easier to include an external page in the dialog so I can create my own form from scratch and easily control it with Jquery.
// Opens a HTML page inside a TinyMCE dialog and pass in two parameters
editor.windowManager.open({
title: "My PHP/HTML dialog",
url: 'mydialog.php',
width: 700,
height: 600
}, {
content: tinymce.activeEditor.selection.getContent({format: 'html'}),
nodeName: editor.selection.getNode().nodeName
});
Then in mydialog.php interact with the current TinyMCE with:
/* get content from TinyMCE */
console.log(args.content);
console.log(args.nodeName);
/* set content in TinyMCE */
top.tinymce.activeEditor.insertContent('My changed content here');
/* close the dialog */
top.tinymce.activeEditor.windowManager.close();
The reference can be found here:
http://www.tinymce.com/wiki.php/Tutorials:Creating_custom_dialogs
Try to use onPostRender and set the selected value to with the value() function.
Example:
{
type: 'listbox',
name: 'text',
values: [
{text : '1', value : '1'},
{text : '2', value : '2'},
{text : '3', value : '3'}
],
onPostRender: function() {
this.value('2');
}
}
According to their listbox example (https://www.tiny.cloud/docs-4x/demo/custom-toolbar-listbox/) it can be done with onPostRender. I have the following code working in WordPress 5.3.2 (classic editor plugin enabled):
tinymce.PluginManager.add('mybutton', function( editor, url ) {
editor.addButton( 'mybutton', {
type: 'listbox',
text: tinyMCE_object.button_name,
icon: false,
onselect: function (e) {
editor.insertContent(this.value());
},
values: [
{ text: '[one_half]', value: '[one_half] [/one_half]' },
{ text: '[one_third]', value: '[one_third] [/one_third]' },
{ text: '[one_fourth]', value: '[one_fourth] [/one_fourth]' },
{ text: '[one_fifth]', value: '[one_fifth] [/one_fifth]' },
{ text: '[grid]', value: '[grid] [/grid]' },
{ text: '[grid_element]', value: '[grid_element] [/grid_element]' }
],
onPostRender: function () {
// Select the second item by default
this.value('[one_third] [/one_third]');
}
});
});
i have a js view that contain button when i click this button i want to open another view
and it connot work
this is my first view
Ext.define('Ext4Example.view.login.WestMenu', {
extend: 'Ext.panel.Panel',
alias: 'widget.westmenu',
frame:'true',
initComponent: function() {
Ext.apply(this, {
title: 'Writeup',
animCollapse: true,
width: 200,
minWidth: 150,
maxWidth: 400,
iconCls:'logo',
split: true,
collapsible: true,
items: [
{
xtype : 'button',
text:'Ajouter réunion',
action:'meet',
iconCls:'add',
name:'meet',
width:120,
height:30,
x:20,
y:30
}]
});
this.callParent(arguments);
}
});
and this is my second view
Ext.define('Ext4Example.view.login.create-rd', {
extend: 'Ext.window.Window',
alias: 'widget.test',
frame:'true',
initComponent: function() {
var win= Ext.create('Ext.window.Window', {
title: 'Ajouter réunion',
width : 630,
height: 600,
layout: 'fit',
iconCls:'add',
items: [{
xtype: 'form',
id : 'form-widgets',
},
items: [
{
fieldLabel: 'date',
xtype : 'datefield',
name : 'date'
}
],
}
]
}).show();
}
});
and this is my controller
Ext.define('Ext4Example.controller.Login', {
extend: 'Ext.app.Controller',
refs: [{
ref: 'Home',
selector: 'home'
},
{
ref: 'Login',
selector: 'login'
}
],
stores: ['Login'],
models: ['Login'],
views: ['login.LoginForm','login.HomePage','login.CenterPanel','login.WestMenu','login.create-rd'],
init: function() {
this.control({
'login button[action=reset]': {
'click' : function(button, event, opt) {
var form = button.up('form');
form.getForm().reset();
}
},
'login button[action=connect]': {
'click' :this.connect
},
'login button[action=meet]': {
'click' :this.meet
}
});
},
connect:function()
{
this.getLogin().close();
var view1 = Ext.widget('home');
},
meet:function()
{
this.getHome().close();
var view2 = Ext.widget('test');
}
});
please any one have a solution of this
You have nothing that matches login. The selector login button[action=reset] means "Find a button xtype, with an attribute action, with a value reset, that exists as a child item under a container with xtype login".
It's the last past of your selector that's not satisfied.
Change the selector to:
westmenu button[action=reset]