In this example we we are going to show how we wrote a Notes plugin for MobileX.
This plugin will create a Notes button on company and person screens.
When you click on this it will display a list of the top 10 notes against the given company or person.
So from the CRM server we create a folder called Notes in the MobileX plugin folder.
and under that folder create two folders called “client” and “server”.
Create a file in the “server” folder called viewNotesList.js This file will be called from the client (plugin.js) to get the data from the Notes Table.
Create a file in the “client” folder called plugin.js (it must have this name).
This file is downloaded to the client and is what we use to create the button and render a list (when the button is clicked)
This file has 2 core Methods that must be implemented
var onDocumentReady = function () {}
var onContextChanged = function () {}
In this example we use onContextChanged as this is called when the Context (entity) changes.
onDocumentReady is called when the page is loaded.
To enable the plugin we update the web.config file in
custompages/sagecrmws/
to add in the plugin (folder name)
<add name=”Notes” />
We implement onContextChanged as follows:
var onContextChanged = function () {
if (cApp.EntityName.toLowerCase().indexOf(“company”) == 0) {
var _posx = helpers_getMenuLeftPosInc() + helpers_getMenuLeftPosInc() + helpers_getMenuLeftPosInc() + helpers_getMenuLeftPosInc() + helpers_getMenuLeftPosInc() + helpers_getMenuLeftPosInc()+ 5;
var _posy = 2;
Factory.destroyComponent(“btnNotesListCompany”);
cApp.btnNotesListCompany = Factory.createTopButton(“btnNotesListCompany”);
cApp.btnNotesListCompany.pr_caption = “Notes”;
cApp.btnNotesListCompany.pr_icon = “square-o fa-lg”;
cApp.btnNotesListCompany.pr_onclick = “cApp.viewNotesList(cApp.EntityName,cApp.EntityId);”;
cApp.btnNotesListCompany.pr_insert = true;
cApp.btnNotesListCompany.draw(“btnContainer”);
cApp.btnNotesListCompany.position(_posx, _posy);
} else
if (cApp.EntityName.toLowerCase().indexOf(“person”) == 0) {
var _posx = helpers_getMenuLeftPosInc() + 255;
var _posy = 2;
Factory.destroyComponent(“btnNotesListPerson”);
cApp.btnNotesListPerson = Factory.createTopButton(“btnNotesListPerson”);
cApp.btnNotesListPerson.pr_caption = “Notes”;
cApp.btnNotesListPerson.pr_icon = “square-o fa-lg”;
cApp.btnNotesListPerson.pr_onclick = “cApp.viewNotesList(cApp.EntityName,cApp.EntityId);”;
cApp.btnNotesListPerson.pr_insert = true;
cApp.btnNotesListPerson.draw(“btnContainer”);
cApp.btnNotesListPerson.position(_posx, _posy);
}
};
- cApp.EntityName contains the name of the current entity
- Factory.createTopButton – this creates the Notes button and we position this absolutely
- viewNotesList – this is a method we add now to the plugin.js
cTSApp.prototype.viewNotesList = function (EntityName, EntityId) {
var params = {
fileName: “js\\plugins\\Notes\\server\\viewNotesList.js”,
EntityId: EntityId,
EntityName: EntityName
};
var viewNotesListCompleted = function (data) {
cApp.drawNotesList(data);
};
var viewNotesListCompleted2 = function (data) {
cApp.drawNotesList2(data);
};
var useList = false;
if (useList)
{
//normal table list
cApp.gatewayPostParams(“runServerScript”, params, viewNotesListCompleted);
} else {
//nicer list with multiple items
cApp.gatewayPostParams(“runServerScript”, params, viewNotesListCompleted2);
}
};
In viewNotesList method we make a request to the server file viewNotesList.js
The method “gatewayPostParams” is used to make the server request. It takes a parameter object with the context data and also a call back.
We have 2 example of call backs here. One renders a list and the other is a list of screens. Change useList to toggle between the two.
In the server script we create our query and return the data as JSON
if (params.EntityId) {
var noteidfield = “Note_ForeignId”;
var Note_ForeignTableId=”-1″;
if (params.EntityName.toLowerCase() == “company”) {
Note_ForeignTableId=”5″;
} else
if (params.EntityName.toLowerCase() == “person”) {
Note_ForeignTableId=”13″;
}
var sql = “select * ” +
” from notes ” +
” where {0}={1} and {2}={3} order by 1 desc”;
sql = clr.System.String.Format(sql, ‘Note_ForeignTableId’, Note_ForeignTableId, noteidfield, params.EntityId);
var jsonResult = SQLJSONSerializer.ExecuteQueryToJSON(sql, false);
Response.Write(jsonResult);
}
The request script gets the params object which contains the parameters from the request.
SQLJSONSerializer.ExecuteQueryToJSON – This executes the SQL and returns the data in JSON format.
To render the returned data we then implement our callbacks
List
cTSApp.prototype.drawNotesList = function (data) {
var originalEntityName = cApp.EntityName;
var originalEntityId = cApp.EntityId;
cApp.container.clear();
// NOTE: we can’t use JSON.parse or $.parseJSON since
// JSON string contains JS expressions to format date(s) on client
this.notesdata = eval(“(function() { return ” + data + “; })()”);
var params = {
fileName: “js\\” + _getEntityMenu(),
EntityId: originalEntityId,
EntityName: originalEntityName
};
cApp.gatewayPostParams(“runClientScript”, params, context_changed_callback);
// alert(JSON.stringify(this.notesdata));
cApp.pnlNotesListHeading = cApp.createLabelTitle(“pnlNotesListHeading”, “Notes”);
cApp.pnlNotesListHeading.pr_onclick = “”;
cApp.pnlNotesListHeading.pr_width = helpers_getPanelWidth();
cApp.pnlNotesListHeading.draw(“container”);
cApp.pnlNotesListHeading.position(0, 47);
Factory.destroyComponent(“NotesListPanelContent”);
cApp.NotesListPanelContent = Factory.createPanel(“NotesListPanelContent”);
cApp.NotesListPanelContent.pr_BackColor = “”;
cApp.NotesListPanelContent.pr_className = “stEntitySummaryContainerItem”;
cApp.NotesListPanelContent.draw(“container”);
cApp.NotesListPanelContent.position(0, 92);
cApp.NotesListPanelContent.setWidth(Factory.deviceObject.pr_width);
Factory.destroyComponent(“NotesTable”);
var NotesTable = Factory.createTable(“NotesTable”);
NotesTable.pr_className = “table table-striped margin-top”;
var headerRow = NotesTable.addRow(“NotesTableHeaderRow”);
headerRow.isheader = true;
headerRow.addCell(“header_note_note”).pr_value = “Note”;
headerRow.addCell(“header_note_createddate”).pr_value = “Date”;
for (var i = 0; i < this.notesdata.length; ++i) {
var note = this.notesdata[i];
var row = NotesTable.addRow(“NotesTableRow” + i);
row.pr_height = “32px”;
row.addStyleAttr(“cursor”, “pointer”);
var onRowClick = “cApp.viewNoteItem({0});”.format(i);
var libr_noteCell = row.addCell(“NotesTableRow” + i + “_refid”);
libr_noteCell.pr_value = note.note_note;
libr_noteCell.pr_onclick = onRowClick;
libr_noteCell.pr_width = “60px”;
var dateCell = row.addCell(“NotesTableRow” + i + “_date”);
dateCell.pr_value = note.note_createddate;
dateCell.pr_onclick = onRowClick;
dateCell.pr_width = “60px”;
}
NotesTable.draw(“NotesListPanelContent”);
NotesTable.positionRel(10, 0);
}
================================
List of Screens
cTSApp.prototype.drawNotesList2 = function (data) {
Factory.destroyComponent(“pnlNotesListHeading”);
Factory.destroyComponent(“NotesListPanelContent”);
var originalEntityName = cApp.EntityName;
var originalEntityId = cApp.EntityId;
cApp.container.clear();
cApp.pnlNotesListHeading = cApp.createLabelTitle(“pnlNotesListHeading”, “Notes”);
cApp.pnlNotesListHeading.pr_onclick = “cApp.viewNotesList(cApp.EntityName, cApp.EntityId);”;
cApp.pnlNotesListHeading.pr_width = “150px”;
cApp.pnlNotesListHeading.draw(“container”);
cApp.pnlNotesListHeading.position(0, 47);
// NOTE: we can’t use JSON.parse or $.parseJSON since
// JSON string contains JS expressions to format date(s) on client
this.notesdata = eval(“(function() { return ” + data + “; })()”);
// alert(this.notesdata);
var params = {
fileName: “js\\” + _getEntityMenu(),
EntityId: originalEntityId,
EntityName: originalEntityName
};
cApp.gatewayPostParams(“runClientScript”, params, context_changed_callback);
Factory.destroyComponent(“NotesListPanelContent”);
cApp.NotesListPanelContent = Factory.createPanel(“NotesListPanelContent”);
cApp.NotesListPanelContent.pr_BackColor = “”;
cApp.NotesListPanelContent.pr_className = “stEntitySummaryContainerItem”;
cApp.NotesListPanelContent.draw(“container”);
cApp.NotesListPanelContent.position(0, helpers_getpanelContentYpos());
cApp.NotesListPanelContent.setWidth(Factory.deviceObject.pr_width);
for (var i = 0; i < this.notesdata.length; ++i) {
var note = this.notesdata[i];
var stnotesSummaryContainer = Factory.createPanel(“stnotesSummaryContainer” + i);
stnotesSummaryContainer.pr_BackColor = “white”;
stnotesSummaryContainer.draw(“NotesListPanelContent”);
stnotesSummaryContainer.setWidth(Factory.deviceObject.pr_width – 10);
Factory.destroyComponent(“stnotesSummary” + i);
var stnotesSummary = Factory.createTable(“stnotesSummary” + i);
stnotesSummary.pr_className = “table table-noborder margin-top”;
stnotesSummary.pr_BackColor = “white”;
var _gateway = joinUrl(Factory.CRMurl, acceleratorConfig.webServicePath);
TSFactoryUtils.addPropertyRow(“note_noteid”, stnotesSummary, “Note”, “Note:”, note.note_note, “”, “”, “alert(” + note.note_note+ “);”, “”);
stnotesSummary.draw(“stnotesSummaryContainer” + i);
}
}
That’s it.
Easy 🙂
Okay you download it from here