How to insert a table inside a contentControl using Word javascript api - ms-word

I am developing a word add-in using word JavaScript api, I need to insert some data in table format inside the content Control and placed that content control on top of document.
Please advice.
Thanks.

This should be quite a simple operation. I am assuming that by "On top" of the document you mean inserting a table where the document starts. First line.
All the insertion methods have an insertionLocation parameter that you can use for that purpose. On this case you want to do a body.isnertTable, the 3rd parameter is the insertionLocation ("start" is sent to insert at the beginning of the body of the document).
Once its inserted you can actually wrap it with a content control. Check sample below for details. I included other details, such as applying a built-in style to the inserted table.
hope this unblocks you. thx!
function insertTableAndWrapWithCC() {
Word.run(function (context) {
// We need a 2D array to hold the initial table values
var data = [["Apple", "Orange", "Pineapple"],["Tokyo","Beijing", "Seattle"]];
var table = context.document.body.insertTable(3, 3, "start", data);
table.styleBuiltIn = Word.Style.gridTable5Dark_Accent2;
//now we insert the content control on the table.
var myContentControl = table.insertContentControl();
myContentControl.title = "CC Title";
return context.sync()
})
.catch(function (e) {
console.log(e.message);
})
}

Related

How to get the current active table (where currently the cursor is positioned) in Word using Office.js api?

I want to get the content of a table ,by just clicking on the table(not selecting the table) i.e placing the cursor on the table, in Word Add-in using Office Js Api.
The Word JS API has (since release of Requirement Set 1.3) the parentTable and the ParentTableOrNullObject properties of the Range object.
Since document.GetSelection() returns a Range object, code like the following sample will evaluate whether the current selection is in a table. (It also counts the number of rows and selects the table.)
const range = context.document.getSelection();
range.load("parentTableOrNullObject");
await context.sync();
var isInTable = range.parentTableOrNullObject;
if (isInTable.isNullObject) {
messageText = "The selection is not in a table."
}
else {
var tblRows = isInTable.rowCount;
isInTable.load("rowCount");
await context.sync();
var messageText =
"The selection is in a table with " + tblRows.toString() + " rows.";
isInTable.select();
}
console.log(messageText);

UI5 - how to dynamically bind data to a Select in Table, depending on another combobox?

I have a classic situation - a table with two comboboxes (or, to be exact, sap.m.Select controls) and after select in the first one, I would like to have the values in the second one updated. This is my model, basically, the first combobox should contain the list of available states and once some is selected, the second sap.m.Select control should be populated by relevant cities
{
countries: [
{ country: 'France', cities: ['Paris', 'Marseille', 'Lyon']},
{ country: 'Germany', cities: ['Berlin', 'Bonn']}
]
}
The problem is that I dont know how to do it. I am able to get the id of the updated row using something like this.
onCountryChange: function (oEvent) {
const selectedItem = oEvent.getParameter("selectedItem");
var path = selectedItem.getBindingContext().getPath();
bindComboBox(path); // this should rebind the data, but not written yet
}
I know now I should rebind the data in the correct combobox, however, I don't know how to affect only that single combobox on the correct row and how to update it. Could someone advise me how to do it? The whole table is defined in the .xml view, can I do it also with a formatter or inline expression or is this scenario too difficult for that?
Thank you
You can use the bindAggregation method (from the ManagedObject) class to rebind the combo boxes' items.
onCountryChange: function (oEvent) {
const selectedItem = oEvent.getParameter("selectedItem");
var path = selectedItem.getBindingContext().getPath();
this.byId("combo2").bindAggregation("items", {
path: path + "/cities",
template: new sap.ui.core.Item({
key: "{}",
text: "{}"
})
});
}
Note: Replacing "combo2" with the id of your 2nd combo box/select control.
Edit: To get the correct combo box (assuming you have multiple created on a table, use the ID of the first combo box (oEvent.getSource().getId()) to generate the ID of the 2nd combo box. Without knowing more of the structure of the table (and how it's created) I can't offer more.

How to insert a ContentControl inside another ContentControl in word using Javascript Api

I need to insert a contentControl that will contain a table and wrap this ContentControl inside another parent contentControl. Currently contentControl that contain table data inserted correctly but when i tried to get the current selection and inserting the CC, word showing message 'Rich Text control can not inserted around multiple selection'.
Please advice how i can insert CC and wrap inside another parent CC. Thanks.
Don't do it on the selection. Get the range of the content control wrapping the table and then insert another wrapper.
like this:
function insertTableWrappedBy2CCs() {
Word.run(function (context) {
// We need a 2D array to hold the initial table values
var data = [["Apple", "Orange", "Pineapple"],["Tokyo","Beijing", "Seattle"]];
var table = context.document.body.insertTable(3, 3, "start", data);
table.styleBuiltIn = Word.Style.gridTable5Dark_Accent2;
var myCC = table.insertContentControl();
myCC.title = "table";
var cc2 = myCC.getRange().insertContentControl();
cc2.title = "parent";
return context.sync()
})
.catch(function (e) {
console.log(e.message);
})
}
thanks!!!

link multiple models on same row of sap.m.table

This may be a basic question, but it's my first, so please be kind :-).
I have a sap.m.table with two models, one model with transaction data (trxModel) and another model that is used to display a sap.m.select list (reasonCodeModel). The table model is set to trxModel.
The selected value key from the dropdown needs to update a value (ReasonCodeID) in the trxModel when a value from the reason code list is selected.
I can retrieve the selected key in the change event as so
var selKey = evt.getParameter("selectedItem").getKey();
Is there a simple way to find the trxModel relevant model path from the table row Select list value I've just modified? Or is it possible to bind the ReasonCodeID from the trxModel to the ReasonCodeID field in the reasonCodeModel?
Just an extra piece of info, The current row is selected and is accessible
var selItem = dtlTable.getSelectedItem();
2nd question and I guess could be kind of related, is there a way of getting the table model path based on the selected item (highlighted row) of the table? And vice a versa?
More details on Select & Table binding.
var tabTemplate = new sap.m.ColumnListItem(
{
::
new sap.m.Select(
"idReasonCodeSelect",
{
enabled : false,
change : function(evt) {
oS4View.getController().changeReasonCodeSel(evt);
}
}
),
Bind the resource code Select to the Table
// bind the reason codes to the reason code model
sap.ui.getCore().byId("idReasonCodeSelect").setModel(
oReasonCodeModel);
sap.ui.getCore().byId("idReasonCodeSelect").bindAggregation("items", "/results",
new sap.ui.core.Item({
key : "{ReasCodeID}",
text : "{ReasCodeDesc}"
}));
Per Qualiture comment, how do I bind the Select key to the table model ReasonCodeID value?
I found an approach to tackle the first part of my question above
From the change function on the Select, I can find the path of the table model using the following.
var path = evt.getSource().getParent().getBindingContext().sPath;
2nd Update:
On the selectionChange event on the table, there's a couple of options to find the associated model path or model content.
// find the model path
oModelPath = selItem.getBindingContext().getPath();
// model values
oItem = oEvent.getParameter("listItem").getBindingContext().getObject();
So my only remaining issue, While I loop through the table model results (trxModel) and I want the Select List (using setSelectedKey) to reflect the ReasonCodeID value in the trxModel.

Update multiple records at once using SailsJS

So I'm making this app where I will have menu items for a restaurant right ?
The owner should have the ability to move around the menu items
This is my menuitem.js Model contains
name , price , position
That's it. Super simple.
So to reposition these elements I will use jquery UI
So the final product will be something very similar to this > http://jqueryui.com/sortable/
So my goal is to save the position of each of these menu items on the database every time one of the menu items has been changed. So I thought Sails must have a function that can update all records at once
Like below
Menuitem.update([{id: 1},{position: 3}], [{id: 2},{position: 3}] ).exec(function(err, updatedRecords) {
if (err) {
return res.send({message: 'Could not update the records', err: err}, 500);
}
if (updatedRecords) {
return res.send({ records: updatedRecords }, 200);
} else {
return res.notFound('Records not found');
}
});
Any help would be greatly appreciated
Also opened an issue on SailsJS
https://github.com/balderdashy/sails/issues/2404
You can achieve this using a native SQL query. To execute native SQL queries, you need to use Model.query() function of waterline. In your case it will be something like this.
var myQuery = "update menuitem set .... complete SQL query goes here ";
Menuitem.query(myQuery, function (err, result){
if(err){
// error handling here
}
else{
// do something with result here
}
});
Now, for your native SQL query, you can use case statement to update the rows depending on the position value. For example, if I am moving item from position 4 to position 2, then my query will be like this.
update menuitem
set position = case when position = 4 then 2
when position >=2 then position + 1
else position end;
Ofcourse, 4 and 2 will be supplied dynamically and your query might look more complex since you will also need to handle whether the user is moving an object up or down. But this is how you can achieve this. If you need to execute even more complicated logic, you can create a stored procedure also. That will also be executed by using Model.query. Beware of SQL injection attacks while building your dynamic queries using the parameters supplied by the end user.