Tag Archives: dynamics crm

CRM 2015: Get your field value without losing focus

In CRM 2015 (and most probably in 2013), an entity attribute is not updated with the typed-in value until you exit that particular field via pressing Tab or by clicking somewhere else.

We have a few entities where we don’t necessarily expect the user to exit a field that needs to be validated. Usually these are end-of-form fields, where there’s nowhere else to go in that form, if you get what I mean. If they type a value and save the entity, the value wouldn’t register and the user would get an error, even though they are seeing their typed characters right in front of them.

Pretty confusing.

Seeing this, I wrote a very simple, quick JavaScript function that’s accessible to all our entities, since it resides in what we call our “root” script library. This is unsupported code, but we know and accept the risks; I expect that you understand that before going ahead and implementing this. Here’s the code:

function GetValue (fieldName, getText) {
    var inputType = Xrm.Page.getControl(fieldName).getControlType();

    if (getText == null) getText = false;

    if (inputType == "lookup") {

        if (getText)
            return Xrm.Page.getAttribute(fieldName).getValue()[0].id;
        else
            return Xrm.Page.getAttribute(fieldName).getValue()[0].name;

    }

    if (inputType == "optionset") {

        if (getText)
            return Xrm.Page.getAttribute(fieldName).getText();
        else
            return Xrm.Page.getAttribute(fieldName).getValue();

    }

    if (inputType != "standard") return null;
    var id = fieldName + '_i';
    var inputElement = document.getElementById(id); 
   
    if (inputElement !== null)
        return inputElement.value;
    else
        return Xrm.Page.getAttribute(fieldName).getValue();

}

The first thing we do is check the type of field we’re working with. Using that, we have some code to send back values for lookups and option lists. The parameter getText allows you to get the name or text descriptions if it’s set to true for these type of fields.

We now evaluate if the field is standard type; if not, we return a null value.

Finally, this is the part where we do the switcheroo. We create an id for a DOM element. The reason for this is that when a CRM field gets focus, an HTML input element is created on the fly; this is where you actually type into. As soon as you focus out of the field, that input is gone. The name format for that element is attributeName + “_i”. 

We build that name and then try to get an element with that name in our DOM. We only do it once because your cursor can only be focused in one field at a time. Wrapping things up, we check if the HTML input element exists (meaning that a field has focus and hasn’t been exited by the user). If found, we return the value of this input, otherwise we return the actual attribute.

Pretty straightforward, and works like a charm for us.

Advertisements
Tagged , , , ,

CRM 2011: Who is really running that child process?

We have recently modified a process where the workflow has to check for a particular time range (done through a custom activity) and if the time at the moment is within the range being checked, the process waits for 30 minutes. At the end of those 30 minutes, it submits itself as a child workflow.

This worked as expected, but we ran into an issue: The remainder of the process needs the user identity to correctly process the entity information. When the process runs normally without the wait timeout, there are no issues. But when it falls in the timeout, and then submits itself as the child workflow, the user identity is changed to that of the workflow owner.

That means that if the owner of the process is, say, your local friendly IT guy, that’s who CRM thinks is running the process, and thus any user-based validations will fail.

The solution for this was to have code in the custom activity that looks for the creator of the entity, and then use that as the user ID needed to execute the user identity-related code. How? We created a function for retrieving the entity owner, and we pass the primary entity ID, as follows:

GetEntityOwner(WorkflowContext.PrimaryEntityId)

This is the code that returns the owner information, and we take it from there:

private Guid GetEntityOwner(Guid entityId)
{
    var myEntity = OrganizationService.Retrieve("new_myentity", entityId, new ColumnSet("createdby"));
    var ownerReference = myEntity.GetAttributeValue<EntityReference>("createdby");
 
    return ownerReference.Id;
}

That fixed the problem and now we get the correct owner for the process to finish successfully.

Have fun!

Tagged , , , , , , ,

USD: Keeping the Session Navigator open by default

Here’s an easy tip: If you want the Session Navigator (that’s the navigation area on the left-hand side of the screen) to remain open by default, just head to the Custom Panel hosted control, and look for this line:

<Expander Grid.Column="0" Style="{DynamicResource StretchExpanderStyle}"
ExpandDirection="Left" x:Name="ExpanderSessionDetails"
IsExpanded="false" BorderBrush="White" >

And change isExpanded from “false” to “true”. That’s it! Now your Session Navigator will open by default.

Tagged , , , , , ,