I was looking at creating a simple generic reusable text-only widget in apostrophe-cms so I made the module text-only-widgets.
with the following code
In lib/modules/text-only-widgets/index.js
module.exports = {
extend: 'apostrophe-widgets',
label: 'Section Heading',
beforeConstruct: function (self, options) {
console.log('options.addFields : ', options.addFields)
options.addFields = [
{
name: 'sectionHeading',
label: 'Section Heading',
type: 'string'
}
].concat(options.addFields || [])
}
};
In lib/modules/text-only-widgets/views/widget.html
{{ data.widget.sectionHeading }}
Now I tried using the above widget in one of my pages as below:
<div>
{{
apos.area(data.page, 'aboutUsDescriptionTwo', {
widgets: {
'text-only': {
addFields: [
{
name: 'sectionDescription', // set these fields dynamically
label: 'Section Description', // set these fields dynamically
type: 'string'
}
]
}
}
})
}}
</div>
As shown in the below image, notice even after passing the addFields with label as Section Description to the text-only widget doesn't override the defaults set in the index.js.
I tried console.log on the options.addFields in index.js but it logs undefined as show below, I also tried few different variations but none works.
The addFields option is at the module level, it controls what fields exist for all instances of this widget. It is not an option that can be passed to individual instances of the widget via apos.area. Thus you can't do it in this way.
The correct approach is to create a second module which uses extend to extend the first one and addFields, at the module level, to add the additional field. Then, in your area, you can offer just one of the two widget types, or both, as is appropriate to your needs.
Thus in addition to lib/modules/text-only-widgets/index.js you would also have:
// in lib/modules/text-plus-description-widgets/index.js
module.exports = {
extend: 'text-only-widgets',
label: 'Section Heading and Description',
addFields: [
{
name: 'sectionDescription',
label: 'Section Description',
type: 'string'
}
]
};
And this widget would also have its own widget.html.
Related
I am trying to create a link that links from one shape with a fixed side to another with a different fixed side. Is this possible?
link.router('oneSide', {
side: 'top',
padding: 30
});
https://resources.jointjs.com/docs/jointjs/v3.1/joint.html#routers.oneSide
I'm not sure 'oneSide' should even be in the routers because in the documentation the router only defines the middle points of the path not the start and end.
In either case, the router function must return an array of route points that the link should go through (not including the start/end connection points). The function is expected to have the form function(vertices, args, linkView)
I found out that in defining the links you can specify the anchor which is basically the start and end point. For the shapes there some built-in anchors. We have to use 'left' and 'right' for this case.
Here is my code. It's in TypeScript but I'm sure you can convert it to JS easily if you need to.
makeLink(parentElementLabel, childElementLabel) {
return new joint.shapes.standard.Link({
source: {
id: parentElementLabel,
anchor: {
name: 'right'
}
},
target: {
id: childElementLabel,
anchor: {
name: 'left'
}
},
router: {
name: 'normal'
},
attrs: {
line: {
stroke: 'black',
cursor: 'default',
},
wrapper: {
cursor: 'default'
}
},
// smooth: true,
});
}
I know how to set the optionList on Initiliaztion but how do I set it programmatically?
I have an inviteList array:
$("#select-invite").options(inviteList);
You can use load method to set options via programmatic API. You may also want to call clear and clearOptions methods to reset selected values and old options.
Here is how to put it all together:
var selectize = $("#select-invite")[0].selectize;
selectize.clear();
selectize.clearOptions();
selectize.load(function(callback) {
callback(inviteList);
});
Please note that inviteList should be an array of objects that have properties configured in valueField and labelField options when select was initialized. For example, here is how inviteList should look like with default valueField and labelField options:
var inviteList = [
{
text: 'Option One',
value: 1
},
{
text: 'Option Two',
value: 2
}
];
As far as I know there's no method for adding multiple options through the API. You'll need to write a loop that uses the addOption() method. You'll need to get the control instance of selectize before trying to use the API. Take a look at the example below, from the Github examples:
// Create the selectize instance as usual
var $select = $('#select-tools').selectize({
maxItems: null,
valueField: 'id',
labelField: 'title',
searchField: 'title',
options: [
{id: 1, title: 'Spectrometer', url: 'http://en.wikipedia.org/wiki/Spectrometers'},
{id: 2, title: 'Star Chart', url: 'http://en.wikipedia.org/wiki/Star_chart'},
{id: 3, title: 'Electrical Tape', url: 'http://en.wikipedia.org/wiki/Electrical_tape'}
],
create: false
});
// Get the selectize control instance
var control = $select[0].selectize;
// Add the new option when a button is clicked
// Remove the click event and put the addOption call in a loop
$('#button-addoption').on('click', function() {
control.addOption({
id: 4,
title: 'Something New',
url: 'http://google.com'
});
});
From the Github examples.
I know this is an old question but as of 2021 I have found this to be the simplest way to achieve this:
Building on #byte255's answer above, you only need to use the clearOptions method and addOption method.
let selectize = $("#select-invite")[0].selectize;
selectize.clearOptions();
let newOptions = [
{
text: 'Option One',
value: 1
},
{
text: 'Option Two',
value: 2
}
]
selectize.addOption(newOptions);
Faced with a problem at work with ExtJS
There is such a code - a new class (view)
Ext.define('FormApp.view.ElementContainer', {
extend: 'Ext.Container',
alias: 'widget.elemcontainer',
initComponent: function() {
this.items = [{
layout: {
type: 'hbox',
align: 'middle'
},
items: [
{ xtype: 'component',
html: ' Поиск  '},
{ xtype: 'textfield',
width: 495,
name: 'search'
},
{ xtype:'component',
html:'  '},
{ xtype: 'button',
text: 'Найти',
width: 80,
action: 'searchTreeData'}
]}
];
this.callParent();
}
});
Then in the controller I write code like this to get the value of the textfield
Ext.define('FormApp.controller.ControlOne', {
extend: 'Ext.app.Controller',
views: ['ElementContainer', 'TreeView'],
init: function() {
this.control({
'elemcontainer button[action=searchTreeData]': {
click: this.searchTree
},
'elemcontainer textfield[name=search]':{change: this.str}
});
},
searchTree: function(searchStr) {
var dat = Ext.widget('elemcontainer');
var str = dat.down('textfield').getValue();
alert (str.getValue());
},
str: function()
{alert('OK');}
});
I can not get the value of a text field in extJS
How to access the elements to get their values?
Thanks in advance and sorry for my clumsy English
The problem is that by using Ext.widget(...) in searchTree(), you're creating a new instance of the class (be sure to check the docs), rather than getting the of the component that already exists.
Another issue is that str is already the "value" of the textfield, so calling getValue() on str.getValue() won't get you very far either.
So a few suggestions:
Update you searchTree method to pass the correct arguments. Since this method is getting called on the click event of a button, the arguments will be those of the click event for Ext.button.Button : searchTree( btn, e, opts ) {...}
Once you have the correct arguments being passed to searchTree(), you can then use the component selector methods to get the existing instance of the container. For example, since the button is already a descendant of the container, you can do the following to get the correct instance of the component:
var ctr = btn.up( "elemcontainer" )
And now that you have the correct instance of the container, you can again use one of the component selector methods to find the textfield:
var str = ctr.down( 'textfield' ).getValue()
I need to have different layouts when render a view (Expressjs 2.x). How to change them ?
For example:
res.render('follow_page', {layout:'layout_2'}, {name:'test'})
res.render('user_page', {layout:'layout_1'}, {user:'test1'})
For Express 2.x and earlier, you'll want to merge the 2 objects, giving it a locals property:
res.render('follow_page', { layout: 'layout_2', locals: { name: 'test' } });
res.render('user_page', { layout: 'layout_1', locals: { name: 'test1' } });
I have several records of the same type that I want to show on the screen. I thought about creating several panels that will print the data of each record. I chose this solution because data structure is too complex to be printed in a simple grid. Here is a simplified example of that structure :
{
label: 'myLabel',
{
attr1: 'value1',
attr2: 'value2'
}
startValidityDate: oneDay,
endValidityDate: anotherDay
}
I try to add dynamically nested panels in my current panel :
var myStore = new Ext.data.Store({
id: 'myStore',
restful: true,
idProperty: 'OID',
root: 'tbas',
proxy: myProxy,
reader: myReader,
autoLoad: false,
listeners: {
'load': function(data){
var records = data.getRange();
var currStore = null;
for(var i=0; i<records.length; i++) {
currStore = new Ext.Panel({
layout:'vBox',
items: [{
xtype: 'textfield',
fieldLabel: I18nManager.get('label_ttbaUI_label'),
name: 'tbaLabel',
value: records[i].data.tbaLabel
},{
xtype: 'textfield',
fieldLabel: I18nManager.get('label_ttbaUI_label'),
name: 'tbaOid',
value: records[i].data.tbaoid
}]
});
recordList.add(currStore);
console.log("------------------------------");
console.log(currStore);
}
recordList.doLayout();
}
}
});
var recordList = new Ext.Panel({
id: 'recordList',
renderTo: 'recordPart',
layout:'vBox',
title: I18nManager.get('label_ttbaUI_selected_tariffs')
});
recordList.doLayout();
In the firebug console, the UI objects seems to be ok.
My problem is that the recordList elements are not visible
I can see that they exist in the FB console, but they are not well printed on the screen.
Did I forgot something that make the elements hidden ? or bad printed ?
I'm sure that it is a CSS problem, some trouble with ext-all.css : when I remove the content of that CSS, I can see my fields
There must be something wrong in the way I wrote the code so that it causes the render problem WDYT ???