I'm working on an application that will allow people to select which data fields they would like a form to have. I had it working but when I tried to move the form fields into a table for a bit of visual structure I'm running into a problem.
// Now print the form to a new div
array.forEach(selectedFields, function(item, i) {
var l = domConstruct.create("label", {
innerHTML: item + ': ',
class: "dataFieldLabel",
for: item
});
var r = new TextBox({
class: "dataField",
name: item,
label: item,
title: item
});
var a = domConstruct.toDom("<tr><td>" + l + r + "</td></tr>");
domConstruct.place(a, "displayDataForm");
When I run the code I can select the fields I want but instead of textboxes being drawn on the screen text like:
[object HTMLLabelElement][Widget dijit.form.TextBox, dijit_form_TextBox_0]
[object HTMLLabelElement][Widget dijit.form.TextBox, dijit_form_TextBox_1]
Is printed to the screen instead. I think this is because I am passing domConstruct.place a mixture of text and objects. Any ideas about how to work around this? Thanks!
Try this :
require(["dojo/_base/array", "dojo/dom-construct", "dijit/form/TextBox", "dojo/domReady!"], function(array, domConstruct, TextBox){
var selectedFields = ["Foo", "Bar", "Baz"];
array.forEach(selectedFields, function(item, i) {
var tr = domConstruct.create("tr", {}, "displayDataForm"),
td = domConstruct.create("td", {}, tr),
l = domConstruct.create("label", {
innerHTML: item + ': ',
'class': 'dataFieldLabel',
'for': item
}, td, 'first'),
r = new TextBox({
'class': 'dataField',
name: item,
title: item
}).placeAt(td, 'last');
});
});
This assumes you have this in your html :
<table id="displayDataForm"></table>
Don't forget to quote "class" and "for" as these are part of javascript's grammar.
The domConstruct functions will not work with widgets. You can create the html and then query for the input node and create the test box.
var root = dom.byId("displayDataForm");
domConstruct.place(root,
lang.replace(
'<tr><td><label class="dataFieldLabel" for="{0}>{0}:</label><input class="inputNode"></input></td></tr>',
[item])
);
query('.inputNode', root).forEach(function(node){
var r = new TextBox({
'class': "dataField",
name: item,
label: item,
title: item
});
});
Craig thank you for all your help, you were right except that in the call to domConstruct.place the first argument is the node to append and the second argument is the refNode to append to. Thank you.
// Now print the form to a new div
array.forEach(selectedFields, function(item, i) {
var root = dom.byId("displayDataForm");
domConstruct.place(lang.replace(
'<tr><td><label class="dataFieldLabel" for="{0}">{0}: </label><input class="dataField"></input></td></tr>',
[item]), root
);
query('.dataField', root).forEach(function(node) {
var r = new TextBox({
'class': "dataField",
name: item,
label: item,
title: item
});
});
});
Related
I have a panel (Categories) which contains child "questions" (input boxes).
The Panels are displaying fine, but each Panels content: property can include more the one question.
var oPanel = new sap.m.Panel({
expandable: true,
expanded: false,
headerText: oData.results[0].CategoryDesc,
id: "Panel" + index,
content: _.each(oViewData.categories, function(result, index2) {
new sap.m.Input("iCategory" + index + index2, {
});
})
});
oPanel.placeAt("panelContent");
I'm retrieving the data fine, but the content won't render. I'm getting the error message:
The renderer for class sap.ui.core.Control is not defined or does not define a render function! Rendering of __control0 will be skipped! -
Is it possible to use _each (underscoreJs) in the content property? If not, what are my alternatives?
you can push your data to an array and use it in the content area:
var oPanelContent = [];
_.each(oViewData.categories, function(result, index2) {
oPanelContent.push(new sap.m.Input("iCategory" + index + index2, {
})
);
var oPanel = new sap.m.Panel({
expandable: true,
expanded: false,
headerText: oData.results[0].CategoryDesc,
id: "Panel" + index,
content: oPanelContent
})
});
oPanel.placeAt("panelContent");
I create several treetables, each is placed on it's own div.
The main reproducable problem i've got:
creating the tables directly -> everything looks fine (see image 1)
creating the tables within an asynchron jQuery call: the first added table gets always a vertical scrollbar (see image 2)
here is the code:
var oData = { root: ...}
// code for image 2
jQuery.getJSON(url, function (result) {
createTable(oData['table1'], 'table1')
createTable(oData['table2'], 'table2')
})
// code for image 1
createTable(oData['table1'], 'table1')
createTable(oData['table2'], 'table2')
function createTable(oData, codeSample){
var oTable = new sap.ui.table.TreeTable({
columns: [
new sap.ui.table.Column({label: "trans_class", template: "trans_class"})
, new sap.ui.table.Column({label: "Checked", template: "checked"})
],
height: '100%',
selectionMode: sap.ui.table.SelectionMode.None,
enableColumnReordering: false,
expandFirstLevel: false,
visibleRowCount : INITIAL_ROW_COUNT_IN_TABLE,
visibleRowCountMode : sap.ui.table.VisibleRowCountMode.Auto,
toggleOpenState: function(oEvent) {
var isLeafExpanded = oEvent.getParameter("expanded");
if(isLeafExpanded){
oTable.setVisibleRowCount(oTable.getVisibleRowCount() + 2)
SUM_INDEX_TOGGLE = SUM_INDEX_TOGGLE + 2
}else{
oTable.setVisibleRowCount(oTable.getVisibleRowCount() - 2)
SUM_INDEX_TOGGLE = SUM_INDEX_TOGGLE - 2
}
}
})
var oModel = new sap.ui.model.json.JSONModel();
oModel.setData(oData);
oTable.setModel(oModel);
sap.ui.getCore().setModel(oModel, codeSample);
oTable.bindRows("/root");
oTable.expand(4); // expand Sum Row
//Bring the table onto the UI
oTable.placeAt(codeSample);
}
How can I fix this issue. I want that all my tables look the same.
Workaround: add a simple textField and hide it after adding the treeTable:
addSimpleHiddenTextField(HIDDEN_TEXTFIELD)
for(var i in config.TABLES){
createTableAndPlaceIt(result[i], i, config.TABLES[i])
}
hideSimpleTextField(HIDDEN_TEXTFIELD)
Table in a project is now implemented like this:
<table datatable="" dt-options="vm.dtOptions" dt-columns="vm.dtColumns" class="table table-custom"></table>
The code related to this table:
vm.dtColumns = [
DTColumnBuilder.newColumn('id', 'Login ID'),
DTColumnBuilder.newColumn('username', 'User Name'),
DTColumnBuilder.newColumn('email', 'Email'),
DTColumnBuilder.newColumn('usergrouproles', 'User Group Role'),
DTColumnBuilder.newColumn(null).withOption('defaultContent', '<button>button1</button><button>button2</button>').notSortable(),
DTColumnBuilder.newColumn(null).withOption('defaultContent', '<button>button3</button><button>button4</button><button>button5</button>').notSortable()
];
vm.dtOptions = DTOptionsBuilder
.newOptions()
.withBootstrap()
.withFnServerData(serverData)
.withDataProp('data')
.withOption('processing', true)
.withOption('serverSide', true)
.withOption('paging', true)
.withOption('rowCallback', function(row, data, index){
console.log("test rowCallback");
})
function serverData(sSource, aoData, fnCallback, oSettings) {
var draw = aoData[0].value;
var _order = aoData[2].value[0].dir.toUpperCase();
var _start = aoData[3].value;
var _end = _start + aoData[4].value;
var _sort = aoData[1].value[aoData[2].value[0].column].data;
UserSvc.getUsersPaginated(_start, _end, _order, _sort).then(function(result){
var records = {
'draw': draw,
'recordsTotal': result.length,
'recordsFiltered': result.totalCount,
'data': result
};
fnCallback(records);
});
}
For now, it seems okay except the User Group Role column - data there is in form of the object that is why I need to expand it there using ng-repeat. I'm aware of initComplete callback that I will be to apply finally but i cannot get how would I perform expand itself. I mean i want to operate in each cell but i have only an access to the whole row. I gave a try a renderWith() function in vm.dtColumns but it doesn't work at all. Could you show me the right direction?
Finally i found it. It's managed by createdCell option like .withOption('createdCell', withCreatedActionsCell).
I have a table when I try to bind the column of this table to a json data. It works in one of my tables and in other tables it doesn't show anything. I checked content and the way I get the json data and it is exactly the same in all tables.
oTable.addColumn(new sap.ui.table.Column({
label: new sap.ui.commons.Label({text: "Names"}),
template:
new sap.ui.commons.Link({
text:"{name}",
})
}));
the table that shows the content sits in shell and other tables that show nothing sit inside sap.ui.ux3.ThingGroup. I am wondering if the reason that I don't see the binding is because of ThingGroup or not? because as soon as I change the sap.ui.commons.Link to sap.ui.commons.TextView it works.
The cut down version of my code is:
addLayerTable: function(){
var jsonData1 = {
"layers" : []
};
$.getJSON(URI, {}).done(function(data) {
if(data.layers !== undefined){
$.each(data.layers, function(i, field) {
jsonData1.layers.push({
"name" : field
});
});
}
layerDetailPage(jsonData1);
}).fail(function() {
alert("Error while reading layers Data or layers do not exist");
});
var oTable = new sap.ui.table.Table({
rows:{
path:"/layers",
},
width: "900px",
visibleRowCount: 10,
navigationMode : sap.ui.table.NavigationMode.Paginator
});
oTable.addColumn(new sap.ui.table.Column({
label: new sap.ui.commons.Label({text: "Names"}),
template:
new sap.ui.commons.Label({
text:"{name}"
})
}));
function layerDetailPage(layerData){
var oModel = new sap.ui.model.json.JSONModel();
oModel.setData(layerData);
sap.ui.getCore().setModel(oModel, "layerModel");
oTable.setModel(oModel);
};
var oFC1 = new sap.ui.ux3.ThingGroup();
oFC1.addContent(oTable);
return oFC1;
}
As soon as I change the sap.ui.commons.Label to TextView, names become visible. but at the moment nothing. Funny enough if I add a press function to my table and try to get the name of the row in the table it works although it is not visible.
I created a SplitButton in TinyMCE and I am using a for loop to add buttons, but for some reason the buttons' onclick is always calling the same one (the last from the for loop). It seems every time I add a menu option, the callback is being overwritten.
Let me describe what I mean.
var c = cm.createSplitButton('optionsList', {
title : 'Options',
});
c.onRenderMenu.add(function(c, m){
var Opts1 = options[0];
var Opts2 = options[1];
var Opts3 = options[2];
var sub1 = m.addMenu({title: "Options 1"});
for(var x in Opts1){
sub1.add({title: Opts1[x], onclick: function(){
tinyMCE.activeEditor.execCommand('mceInsertContent',false,Opts1[x]);
}});
}
var sub2 = m.addMenu({title: "Options 2"});
for(var y in Opts2){
sub2.add({title: Opts2[y], onclick: function(){
tinyMCE.activeEditor.execCommand('mceInsertContent',false,Opts2[y]);
}});
}
var sub3 = m.addMenu({title: "Options 3"});
for(var z in Opts3){
sub3.add({title: Opts3[z], onclick: function(){
tinyMCE.activeEditor.execCommand('mceInsertContent',false,Opts3[z]);
}});
}
});
The menus are created correctly, but for example if I select 'Options 1' and select any option, tinyMCE will print the last option from that subMenu. I don't know how to fix this.
I fixed it, so I'll answer my own question. I needed to use a closure. The solution was:
var insertVar = function(val){
return function(){tinyMCE.activeEditor.execCommand('mceInsertContent',false,val);}
};
var sub1 = m.addMenu({title: "Options 1"});
for(var x in Opts1){
var variable = insertVar(Opts1[x]);
sub1.add({title: Opts1[x], onclick: variable});
}