lit-element update individual child properties efficently - lit-element

I have the following components
my-app: contains a layout-toolbar and a layout-container
layout-container: contains one or more layout-pages
layout-page: contains one or more layout-elements
layout-element: component to visualize certain data, f.e. a styled numeric label.
The layout-container has an options property that is bound to the apps layoutContainerOptions property like this:
<layout-container .options="${this.layoutContainerOptions}"></layout-container>
layoutContainerOptions is initialized like this:
this.layoutContainerOptions = {
name: "Project 1",
pages: [
{
name: "Page 1",
elements: [
{
name: "Element 1",
color: "red"
},
{
name: "Element 2",
color: "yellow"
}
]
},
{
name: "Page 2",
elements: [
...
]
}
]
}
This correctly renders a layout with two pages and some elements. Now the user should be able to use the toolbar to interactively edit selected elements, f.e. to change the color of an element. How do I propagate a property change to a selected child element?
I could use something like
this.layoutContainerOptions.pages[0].elements[0].color = "blue";
this.layoutContainerOptions = Object.assign({}, layoutContainerOptions, { });
This works but seems to be very inefficient because there may be hundreds of elements which all get re-rendered (or don't they?)
What is the most efficient way to update properties of individual child elements?

Related

Tabulator - rowContextMenu - HowTo get which cell the mouse-rightclick is performed

Is it possible to get which cell the right-click context menu is performed with rowContextMenu?
rowContextMenu gives the data for all cells in the row, but I have not found how to get which cell the action happens.
Using contextMenu could be an option, but I want to build the columns-setup serverside as json and load the columns with
table.setColumns(columnsJson)
Setting columns contextmenu as a function is not a valid json,
columns": [
{ "title": "", "field": "age", "sorter": "string", "headerSort": false, "contextMenu": cellContextMenu}
]
And setting the "contextMenu" as a "string" fails with: error: "Uncaught TypeError: o.forEach is not a function"
columns": [
{ "title": "", "field": "age", "sorter": "string", "headerSort": false, "contextMenu": "cellContextMenu"}
]
Any tips on getting which cell the menu is trigged with rowContextMenu?
Or is there maybe a different/better solution builtin in Tabulator?
Reason for building the column setup serverside is that I want to have different context menu based on type of cell-data, and it will vary based on selection by user.
BR
Bjorn
If you want to get the cell that is being clicked on then you need to use the Cell Context Menu instead as this is passed the cell component that has been clicked.
You would then need to assign the menu per cell but this is easy if you define it as an array outside the table and then reference it on each column definition using the contextMenu property:
//define cell context menu
var cellContextMenu = [
{
label:"Reset Value",
action:function(e, cell){
cell.setValue("");
}
},
]
//add header menu in column definition
var table = new Tabulator("#example-table", {
columns:[
{title:"Name", field:"name",contextMenu:cellContextMenu},
{title:"Age", field:"age",contextMenu:cellContextMenu},
{title:"Address", field:"address",contextMenu:cellContextMenu},
]
});

Why is Tabulator textarea losing focus on every key press?

I have a simple Tablulator JS Fiddle at the link below that has 3 columns. The last column (TA Test) has both the formatter and editor set to 'textarea'. Any attempt to enter values into that field result in the cell immediately losing focus on any key press (at least I think that is what is happening). There are no console or other errors and from what I can tell all the Tabulator options are correct.
What am I missing here to make this cell editable as a textarea?
https://jsfiddle.net/gbvam5ck/2
var data = [
{
pid: 1001,
title: "Test One",
Q1: {qid: 1, value: 1},
Q2: {qid: 2, value: null},
},
{
pid: 1002,
title: "Test Two",
Q1: {qid: 1, value: 0},
Q2: {qid: 2, value: "Hello"},
},
];
var columns = [
{title: "PID", field: "pid"},
{title: "Title", field: "title"},
{title: "TA Test", field: "Q2.value",
formatter:"textarea",
editor: "textarea",
editorParams:{
elementAttributes:{
maxlength:"500",
}
},
}
];
var table = new Tabulator("#example-table", {
index:"pid",
height: "100%",
layout: "fitData",
columns,
data: data,
});
It looks to be a bug using the textarea with the table height option set to a percentage. If you use a pixel value, then it works as expected.
I would recommend you fill out a bug report against the github project. https://github.com/olifolkerd/tabulator/issues/new?assignees=&labels=Possible+Bug&template=bug_report.md&title=
The bug report template shows you what information is needed for the bug to be easy to replicate and fix.
(If you don't have a Github account, then I can create the bug report.)

How to make the application layout control dynamic in Xpages

I have been working on making the applicationLayout Custom Control more dynamic, so I can more build and extend Xpages apps more easily.
To that end I am now using the switch facet, which helps immensely.
I also want to soft code the Application Links, Title Links, and Navigation Entries.
I think I can build a data structure in which I just put the values I want and the majority of the app layout is loaded from this.
So I will have an array of appliances in a scope variable, like so:
“App 1”, “App 2”,”App 3” etc.
Then for the Title’s I will have to have something like this:
“App 1”,”Title Bar 1”,”Title Bar 2”,”Title Bar 3”,
“App 2”,”Title Bar 1”,”Title Bar 2”,”Title Bar 3”,”Title Bar 4"
“App 2”,”Title Bar 1”,
So the first Application Link will three title bars, the second 4, etc.
Then for the nav:
“App 1”,”Title Bar 1”,”Nav 1,”Nav 2"
“App 1”,”Title Bar 1”,”Nav 1,”Nav 2”,”Nav 3"
and so on.
If I do this then it will be very easy I think to layout an app.
My question is what data structure is best to use? And should I use three arrays or on 3-dimensial array?
===================================================================
Knut's answer is great, but I cannot seem to loop through the array.
var lenArr:Integer = sessionScope.apps.length;
for (i=0; i < lenArr;++i)
{sessionScope.apps[i].app}
When I do a length on the session.Scope variable it returns a 3, but when I loop through the array it returns null when i=2. There are only 2 items in my array, at least there should be. Here is my code for the sessionScope.
<?xml version="1.0" encoding="UTF-8"?>
<xp:view
xmlns:xp="http://www.ibm.com/xsp/core"
rendered="false"
viewState="nostate"
xmlns:xc="http://www.ibm.com/xsp/custom">
<xp:this.afterPageLoad><![CDATA[#{javascript:sessionScope.apps =
[
{ app: "xpApp1",
titleBars: [
{titleBar: "ccApp1Title1",
navs: ["ccNavApp11Title1Nav1"]
},
{titleBar: "ccApp1Title1",
navs: ["ccNavApp11Title1Nav2"]
}
]
},
{ app: "xpApp2",
titleBars: [
{titleBar: "ccApp2Title1",
navs: ["ccNavApp21Title1Nav1"]
},
{titleBar: "ccApp2Title2",
navs: ["ccNavApp21Title2Nav1"]
}
{titleBar: "ccApp2Title3",
navs: ["ccNavApp21Title3Nav1"]
}
]
},
];
//Now set the selected values
sessionScope.appSelected = "xpApp1";
sessionScope.titleSelected = "ccApp1Title1";
sessionScope.navSelected = "ccNavApp11Title1Nav1";
var uAgent = context.getUserAgent().getUserAgent();
if((uAgent.match("iPhone") !== null || param.platform=="iphone") ||
(uAgent.match("Android") !== null || param.platform=="android") ||
uAgent.match("iPad") !== null){
context.redirectToPage("/mobile.xsp", true);
}else{
context.redirectToPage("/xpApp1.xsp", true);
} }]]></xp:this.afterPageLoad>
</xp:view>
What am I doing wrong?
Use JavaScript's arrays and objects to define your application structure
sessionScope.apps =
[
{ app: "App 1",
titleBars: [
{titleBar: "Title Bar 1",
navs: ["Nav 1", "Nav 2", "Nav 3"]
},
{titleBar: "Title Bar 2",
navs: ["Nav 4", "Nav 5", "Nav 6"]
}
]
},
{ app: "App 2",
titleBars: [
{titleBar: "Title Bar 3",
navs: ["Nav 31", "Nav 32", "Nav 33"]
},
{titleBar: "Title Bar 4",
navs: ["Nav 41", "Nav 42"]
}
]
}
];
You can access the first app with
sessionScope.apps[0].app
the first app's first titleBar with
sessionScope.apps[0].titleBars[0].titleBar
and first app's first titleBar's second nav with
sessionScope.apps[0].titleBars[0].navs[1]
Use a for loop or forEach to get all elements of an array.

CKEDITOR And Styles configuration with only toolbar

I try to configure CKEDITOR in Oracle Framework "Endeca v 11.1.0" but something is wrong.
I can only configure toobar like this :
[
{ name: 'basicstyles', groups: [ 'basicstyles', 'cleanup' ], items: [ 'Bold', 'Italic', 'Underline', 'Strike', 'Subscript', 'Superscript', '-', 'RemoveFormat' ] },
'/',
{ name: 'styles', items: [ 'Styles', 'Format', 'Font', 'FontSize' ] },
{ name: 'colors', items: [ 'TextColor', 'BGColor' ] },
{ name: 'tools', items: [ 'Maximize', 'ShowBlocks' ] },
{ name: 'others', items: [ '-' ] },
{ name: 'about', items: [ 'About' ] }
];
and i cannot configure styles like i want.
By default i have sur styles of ckeditor and it is normal. i have not set a good style.js with good configuration.
I want to configure specific style and i have read somes documentation like this : http://docs.ckeditor.com/#!/guide/dev_styles
but how can i do that in my configuration :
CKEDITOR.stylesSet.add( 'my_styles', [
// Block-level styles
{ name: 'Blue Title', element: 'h2', styles: { 'color': 'Blue' } },
{ name: 'Red Title' , element: 'h3', styles: { 'color': 'Red' } },
// Inline styles
{ name: 'CSS Style', element: 'span', attributes: { 'class': 'my_style' } },
{ name: 'Marker: Yellow', element: 'span', styles: { 'background-color': 'Yellow' } }
]);
How can i set specific style in toolbar configuration only ??
Thx for help
I'm going to give advice that you might not find helpful :) Instead of creating a custom editor for use within Experience Manager (and then having to maintain that during upgrades, etc), it might be better instead to give them an editor UI completely separate from XM. Then, when they have their nice HTML to copy and paste it into XM.
Another idea: Instead of creating a Flex editor directly (like what you're doing), create a light-weight Flex editor that launches a popup window (where that would be a webapp hosted outside of XM directly). Then have that popup window return a block of HMTL as text. This would allow you to create a fancy editor but not be constrained by Flex.
I can't share a full code example for my second recommendation, but in Flex you can open a popup windoww by doing:
ExternalInterface.call("window.open",
popupUrl, "Select Value",
"menubar=1,resizeable=1,width=1000,height=800,location=yes,menubar=yes,scrollbars=1,toolbar=1");
... where popupUrl would be the URL of your exteranl web app.
Then, in the webapp, when you want to pass back a value, you can do:
windowOpener = window.opener.document.xmgrSwfElement;
windowOpener.selectValue(path);
window.close();
In 11.1, configuration file location of CK Editor has been changed. It is moved inside a .jar. Check ToolsAndFrameworks\11.1.0\server\workspace\state\sling_ifcr-11.1.0\startup\25\richTextEditor-11.1.0.jar file for build-config.js
Thx for your answer.
My action :
extract war file "ifcr-11.1.0.war" in
"/ToolsAndFrameworks/11.1.0/server/webapps/ifcr-11.1.0.war"
extract "richTextEditor-11.1.0.jar" in "icfr-11.1.0/WEB-INF/resources/bundles/25"
make modification on file "richTextEditor-11.1.0/content/ckeditor_4.3.3_full/ckeditor/style.js" for my specific style.
I have open build-config.js but i can't see config for styles.
i have rebuild package richTextEditor-11.1.0.jar and ifcr-11.1.0.war and restart tomcat and i can't see modification on ToolsAndFrameworks\11.1.0\server\workspace\state\sling_ifcr-11.1.0\startup\25\richTextEditor-11.1.0.jar.
i have try to delete all files and folder on ToolsAndFrameworks\11.1.0\server\workspace\state\sling_ifcr-11.1.0\startup* and restart tomcat for deploying artifact and other but my folder "ToolsAndFrameworks\11.1.0\server\workspace\state\sling_ifcr-11.1.0\startup\" is empty.
A crazy thing is my webapp run with succes without this folder and files.
are there a cache or other ?

How to add custom child nodes on an initilized fancytree

I have a json response that is parsed through js & made as ul,li tags in javascript. I will then call .fancytree to make these ul li into a fancytree structure.
Now I requirement of clicking an icon within an li element. This click does an ajax call, gets a json response. All that I need to do is add this DOM to existing li tags.
Fancytree removes all my custom classes & builds something of its own. Is there anyway I can fix my problem.
Regards
Sarath
To add your custom css classes please use the API of fancytree. In the demo you have two ways to make that:
$("#tree").fancytree({
// you can use the node property 'extraClasses' like this.
source: [
{title: "Node 1", key: "1", extraClasses="css-class-1 css-class2"},
{title: "Folder 2", key: "2", extraClasses="css-class-1 css-class2", folder: true, children: [
{title: "Node 2.1", key: "3", extraClasses="css-class-1 css-class2"},
{title: "Node 2.2", key: "4", extraClasses="css-class-1 css-class2"}
]}
],
// or you can customize your node on the rendering.
renderNode: function(event, data){
var node = data.node;
$(node.span).addClass("css-class-1 css-class2");
}
};

Resources