Task "Regarding" field not populating from subgrid in CRM 2013 - javascript

I am using CRM 2013 on-premise with UR1 installed
I have a custom entity with a subgrid on it looking at related "tasks" which looks like this:
Whenever I create a task from the subgrid using the "+" button in the top right hand corner of the subgrid; the "Regarding" field of the newly created task remains blank. When it should be populated by a lookup to the record it was created from.
I have javascript on the task entity which checks the "Regarding" field to check what kind of entity it was created from (if it was created from one) and gets certain field values from the calling entity to populate fields on the task.
Since the "Regarding" field is never filled the Javascript never fires - and the fields do not populate.
When the record is saved, if the regarding field is blank (I have not manually filled it in) - it will eventually be populated by the correct record about 10 - 15 seconds later if you refresh the page. Then the correct fields will be populated and the user is able to edit the option set values and save again. This is not ideal for the user as they would like it to be one fluid action.
Is there any way around this problem?
EDIT for future browsers of this question:
Found a partial work around. If you use an "Activity" subgrid rather than a "Task" subgrid the field will populate. This has a drawback though as you cannot edit the "Activity" subgrid's view to show "Task" specific fields.

Ran into this same issue. The way I got around it was to add a look-up to the custom entity on the form (we put this on a hidden tab). When the Task gets created from the custom entity the look-up will be populated. You can then use that look-up to grab the values that you need to populate, including the regarding field. Not the most elegant, but it works.

I also ran into this problem and went with a pure JS approach to resolving. On load of the task form, call populateRegarding().
This works because even though the regarding lookup doesn't populate by default, the query string parameters include _CreateFromType and _CreateFromId values.
This works in 2015, didn't test on earlier versions. Note that it is unsupported.
function populateRegarding() {
var regarding = Xrm.Page.getAttribute("regardingobjectid"),
createFromType = Xrm.Page.context.getQueryStringParameters()._CreateFromType,
createFromId = Xrm.Page.context.getQueryStringParameters()._CreateFromId;
if (!createFromId || !createFromType ||
!regarding || regarding.getValue() !== null) {
return;
}
var entityLogicalName = getEntityLogicalNameFromObjectTypeCode(createFromType);
regarding.setValue([{
id: createFromId,
entityType: entityLogicalName,
name: "Hardcoded Name" // TODO: retrieve name dynamically
}]);
}
// This method uses an undocumented object and is therefore unsupported.
// You could implement a supported version of this function by querying for
// metadata, but that would be very expensive.
function getEntityLogicalNameFromObjectTypeCode(otc) {
var map = Mscrm.EntityPropUtil.EntityTypeName2CodeMap,
logicalName;
otc = Number(otc); // convert string to number
for (logicalName in map) {
if (!map.hasOwnProperty(logicalName)) { continue; }
if (map[logicalName] === otc) {
return logicalName;
}
}
}

Related

Apex Trigger: Use a trigger to update a custom field with data from another object

I am attempting to write a trigger and I relatively new to both Salesforce and Object oriented programming and I am struggling, so any help would be appreciated!
Task Description:
I have two custom objects, Employee, and Position Associate. Position Associate is an object that creates a mapping and record between an employee and a respective position that they hold. I am attempting to write a trigger, that runs any time a Position Associate is created or updated, that takes three fields, Training Start, Training End, and Home Study Start, and populates it with data from the employee object, from the employee that is mapped to the Position Associate record in question. This must be a trigger as opposed to a making the field a lookup value. So while that may be simpler, it is not an option in this scenario
Current Behavior: While I am not getting any errors, after a record is updated, the fields still remain blank.
Code:
trigger MapDatesPA on Position_Employee__c (after insert,after update)
// Create trigger that runs when a new record is inserted or when a record is updated that maps the employee fields //of Home Study Start Date, Training Start and End Dates to Position Assoicate Object
{
//Prevent Iterative Loop
if(checkRecursive.runOnce()){
Map<Id,Employee__c> pm = new Map <Id,_Employee__c>();
Set<Id> empIds = new Set<Id>();
for(Position_Employee__c posEmp: Trigger.new){
if(posEmp.Employee__c != null){
empIds.add(posEmp.Employee__c);
}
}
for(Employee__c emp:[Select Id, HOME_STUDY_START_DATE__c,Training_Start_Date__c,Training_End_Date__c From Employee__c Where Id In :empIds]){
if(pm.containsKey(emp.Id)){
pm.put(emp.id, emp);
}
}
for(Position_Employee__c posemp: Trigger.New){
If(pm.containsKey(posemp.Id)){
posemp.Training_Start_Date__c = pm.get(posemp.Id).Training_Start_Date__c;
posemp.Training_End_Date__c=pm.get(posemp.Id).Training_End_Date__c;
posemp.Home_Study_Start_Date__c=pm.get(posemp.Id).HOME_STUDY_START_DATE__c;}
}
}
}
I believe the issues lies in the last section but I am completely lost as to why and what the error is as the debugger isnt logging anything. I greatly appreciate any help!

Refresh form (Ctrl+F5) doesn't fire Retrieve Plugin in CRM 2011

I need to update entity1 based on creation of entity2 (math calculation)
while the form of entity1 is open.
When I refresh the entity1 form, the field has the old value until I close and open the entity1 form (the caching issue).
I found out that it doesn't fire the Retrieve Plugin. Is there a way to overcome this issue just by refreshing the form?
First and foremost: latest CRM has Xrm.Page.data.refresh() to update form data "automagically" (not to mention the fact that fields self-refresh when changed via plugins).
If upgrading is not an option, I'd setup a "watcher" function like this:
// attach to Form Load event
function keepYourFieldInSync() {
setInterval(function(){
var current = Xrm.Page.getAttribute("yourField");
// Not shown here, basically get the updated value from server
var fetched = fetch_yourField_value_from_OData_or_SOAP();
if(fetched != current){
Xrm.Page.getAttribute("yourField").setValue(fetched);
// if users aren't allowed to set the field by hand, I'd also include this
// and customize the field to be readonly
Xrm.Page.getAttribute("yourField").setSubmitMode("never");
}
}, 1000); // keep it above 500 to avoid killing the browser
}
I use a "trick" like this to recognize status changes in Quotes (another user would activate it while this user was working on the draft) and it works quite well.

Force a SaveForm in Dynamics CRM 2011 using JavaScript

In CRM 2011, I want to be able to force a save of a form. My requirement is as below.
When the user opens the form, I check if a particular field is empty or not.
If it is empty, I want to force a save, thereby triggering a plugin which will set the field.
My current code is as below. This is in the FormOnLoad function which is associated with LoadForm.
if(checkfield == null){
Namespace.Functions.Contact.FormOnSave();
}
else{
// do nothing.
}
Now, this fails with the following line
Can't execute code from a freed script.
I have no clue as to how to proceed further. As a temporary fix, what I have done is the following
if(checkfield == null){
setTimeout('Namespace.Functions.Contact.FormOnSave()',4000);
}
else{
// do nothing.
}
Any advice on why this is happening and how can I fix it without the timeout would be really helpful?
I have had a look at this question and this, but in my case the form does get loaded or has it actually not yet loaded?
Either way, how can I force a save of a CRM form?
You can save the Form by using:
parent.Xrm.Page.data.entity.save();
But It will only trigger if
(Xrm.Page.data.entity.getIsDirty() == true)
However there is a workaround to set IsDirty property true.
Run the Javascript function on PageLoad. Try to update the value of the field which you are planning to populate through plugin:
For e.g.
function OnPageLoad()
{
var yourField = Xrm.Page.getAttribute("new_yourfield").getValue();
if(yourField == null)
{
parent.Xrm.Page.getAttribute("new_yourfield").setValue("any value");
parent.Xrm.Page.getAttribute("new_yourfield").setSubmitMode("always");
parent.Xrm.Page.data.entity.save();
}
}
You could skip all of this mumble jumbo with loading your form twice with Javascript by creating a plugin registered on the read or the entity. (Or better yet and if possible, on the Create of the entity)
The Plugin would just check for the field, and if it's empty, perform whatever logic you need it to to update the field, then save it, and return the updated field (or possibly just populate the value and don't update the database until the user performs the save)

How do I load data for Dojo Dgrid Table using AJAX?

I am exploring using DGrid for my web application. I am trying to have a table similar to this.
The code for the example above is here.
The table uses a memory store as the source of its data - the summary field there is what shows up when we click and expand each row.
I want the details(i.e the text shown when we click a row) to be fetched from the server on clicking on the row instead of being statically loaded along with rest of the page.
How do I modify the above code to be able to do that?
(My requirement is that of an HTML table, each row expandable on clicking, where the data on each expansion is fetched from the server, using AJAX for instance. I am just exploring dgrid as an option, as I get sortable columns for free with dgrid. If there is a better option, please let me know)
EDIT: Basically I am looking for ideas for doing that and not expecting anyone to actually give me the code. Being rather unfamiliar with Dojo, I am not sure what would be the right approach
If your ajax call returns html, you could place a dijit/layout/ContentPane in your renderer, and set the url of the contents you want to fetch in the ContentPane's href property. Assuming that your initial data (the equivalent of the example's memory store) would have a property called "yourServiceCallHref" containing the url you want to lazy load, your could try this :
require(["dijit/layout/ContentPane", ...], function(ContentPane){
renderers = {
...,
table: function(obj, options){
var div = put("div.collapsed", Grid.prototype.renderRow.apply(this, arguments)),
cp = new ContentPane({
href : obj.yourServiceCallHref
}),
expando = put(div, "div.expando", cp.domNode);
cp.startup();
return div;
}
});
If your service returns json, you could probably do something with dojo/request in a similar fashion. Just add your dom creation steps in your request callback and put them inside the div called "expando"...
Another option would be to replace the Memory store by a JsonRest store, and have the server output the same json format than the one you see on the Memory store. That means all the data would be fetched in a single call though...

how to extend asp.net application in this scenario

I have asp.net web application.where i am creating the User as registration for a particular Firm.In this firm there are 3 type of user as of now. as Admin, Dealer, Manager. so according to this I am changing the UI page.
Means When Admin (Admin is default entry) going create let say Dealer, then there is different UI except General information fields (like name ,contact details and all). and when creating the manager there is different UI fields, except than General information fields.
To reuse the page i am using this way , when selected Manager then related his UI fields get only visible, same for dealer. obviously there is a dropdown control from where i am selecting User type.
But some how , later on if one more User type get added by firm, I need to generate functionality according to New User type. how can i handle if I don not want to change existing code. sense is how can i write the generic code so that I should not need to change in code behind or in javascript again.
Where as all this things are in planning and under implementation for now. but before to go a head I must clear this thing. I am planning to change the UI structure in javascript as usual way , i means
if selected User Type is "Dealer then make visible these div's ELSE If User Type is Manager then make visible these divs
I want to write generic javacript , though new user type get added.
You could maintain the field <-> user type relation in a database and dynamically add labels and textboxes in the PageLoad of your Page.
Then when a new type of user comes along you'd simply need to add to your data.
Your user type should also be in a database.
Of course, the code that lets your users create other users would also have to be flexible enough. So you'd need a CanCreate table that dictates who can create what type of user. :)
EDIT Expanded how to build your Content
Actually, I like your idea about storing the html elements in the database. That'd save you using reflection to dynamically get the propertyvalue. However, I don't think you'll be able to use databinding and all that.
So instead I'd do something like this:
public enum ControlType
{
Label,
TextBox,
...
}
Make a table something like
UserType
PropertyName
PropertyLabelName
FieldLabelType (int)
FieldContentType (int)
Then on pageload you get the UserType, pull the data from the table, find the div where you want to put the data and then add the controls like:
(pseudocode)
Control label = null;
switch (FieldLabelType)
{
case ControlType.Label:
var label = new Label()
{
.. all kinds of properties
Text = PropertyLabelName
};
control = label;
break;
case ???
...
}
if (label != null)
fielddiv.Add(label);
Control field = null;
switch (FieldContentType)
{
case ControlType.TextBox:
var textbox = new TextBox()
{
.. all kinds of properties
Text = new Binding( ... Path = PropertyName)
};
control = textbox;
break;
case ???
}
if (field != null)
fielddiv.Add(field);
Of course, you'd need to do some positioning to get it all looking pretty. Perhaps chuck in a table or something in code?

Categories