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.

notes

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.

mobilex_plugin_folderNew Folder

create_notes_folder

and under that folder  create two folders called “client” and “server”.

folders

Create a file in the “server” folder called viewNotesList.js server_notesjsThis 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).

plugin-file

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” />

webconfigplugin

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

notes_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

notes_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

 

 


You may also like

Join our newsletter

Newsletter
Sending