delegateas / XrmDefinitelyTyped

Tool to generate TypeScript declaration files for Dynamics 365/CDS client-side coding.
http://delegateas.github.io/Delegate.XrmDefinitelyTyped/
MIT License
133 stars 53 forks source link

Explanation of Xrm.ExecutionContext<any, any> #259

Open frozzen10 opened 2 years ago

frozzen10 commented 2 years ago

Hello everyone, I would like to ask if someone could explain what can be TSource or TArgs when passing executionContext.

namespace entity_name_form_name {
  var Form: Form.entity_name.Main.form_name;

  export function onLoad(executionContext: Xrm.ExecutionContext<any, any>) {
    Form = <Form.entity_name.Main.form_name>executionContext.getFormContext();
    ... run some logic...
  }

This is how I manage to do it now but I think it can be better way but I don't know what type can I use here and when. Another problem for me is that I have editable subgrid and I would like to write function to be triggered when user selects record image (this is the event I would like to catch on. And in my old way I was doing it by

function onSelectedRecordChanged(ectx) {
    var source = ectx.getEventSource();
    if (source._attributes.getByName("field_logical_name").getValue() !== null) {
        source._attributes.getByName('other_field_logical_name').controls.getAll()[0].setDisabled(true);
    }
}

and now my question is, if it is even possible to take advantage of TypeScript in this case? image This is what Xrm provides, but I do not know what to choose if any. I must say that I am quite new in TypeScript, but it is awesome! Best regards!

skovlund commented 2 years ago

TSource and TArgs allows specification of the return types of getEventSource() and getEventArgs() respectively. These are not typed by default as the return types depends on where the functions are called, documented here end here.

Since we usually don't use either getEventSource() or getEventArgs(), we don't bother with the typings and simply use any.

However, when the functions are needed they should be properly typed. However, the typings depend on where you register your functions.

Typed onLoad example:

namespace entity_name_form_name {
  var Form: Form.entity_name.Main.form_name;

  export function onLoad(executionContext: Xrm.ExecutionContext<
      Xrm.UiModule<Form.entity_name.Main.form_name.Tabs, Form.entity_name.Main.form_name.Controls>,
      Xrm.LoadEventArgs>) {
    Form = <Form.entity_name.Main.form_name>executionContext.getFormContext();
    ... run some logic...
  }

Typed onRecordSelect example: I don't think we generate correct typings for TSource for the onRecordSelect event, but here is an approximation.

function onSelectedRecordChanged(ectx: Xrm.ExecutionContext<Xrm.PageEntity<Xrm.AttributeCollection>, undefined>) {
    var source = ectx.getEventSource();
    if (source.attributes.get("field_logical_name").getValue() !== null) {
        source.attributes.get('other_field_logical_name').controls.get()[0].setDisabled(true);
    }
}

The example uses the generic Xrm.AttributeCollection, which means that it doesn't know which attributes are available and consequently intellisense can't help you with misspelled field names. But it still assists with the getValue and .controls none the less. Alternatively you can replace Xrm.AttributeCollection with Form.entity_name.form_type.form_name.Attributes which will give you typings for all the fields on that form (note that in this example the form should match the entity in the subgrid and not the one on the main form). However, the correct typings should include only the fields in the subgrid, which I don't believe is an AttributeCollection we generate as a typing...

Note that I've made a few changes in order to use supported functions (which are the only ones we generate typings for):

They should all behave identically but the functions I've used are documented and have typings.

frozzen10 commented 2 years ago

Thanks for your reply. I appreciate it. So I think the best way to achieve full typings is to create dedicated form for editable subgrid and then use it in a way you provided.

skovlund commented 2 years ago

That seems like a reasonable conclusion, though I would just go with the Xrm.AttributeCollection myself.

Typings offer a lot, but if a column is removed from your editable grid the typings are not going to detect it (unless the column is removed from the form as well). The typings can of course still be helpful during development, but won't offer the usual compile time error if columns used in your code are removed from your grid.

Additionally, I would like to update my code for the onLoad example, as we do provide specific typings for that:

namespace entity_name_form_name {
  var Form: Form.entity_name.Main.form_name;

  export function onLoad(executionContext: Xrm.OnLoadEventContext) {
    Form = <Form.entity_name.Main.form_name>executionContext.getFormContext();
    ... run some logic...
  }