Announcement

Collapse
No announcement yet.

Using jquerydatatables from retyped

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

    Using jquerydatatables from retyped

    Hello everyone,

    Feel free to move this topic if this is not the correct place.

    I'm currently migrating a project from saltarelle to bridge/retyped.

    I'm using this plugin : https://datatables.net/
    which is available as a retyped plugin (great !).

    However the implementation is a bit strange/difficult, in particular the whole Bridge.Union stuff.
    Below is an example.

    First thing I find odd is the parameter lengthMenu, previously in the implementation I wrote I had a int[][]. Now it is a Union<Union<double, string>[], Union<double, string>[][]>.

    I also had some difficulties using the fonction render :
      
     public Union<double, string, ObjectColumnRender, FunctionColumnRender> render { get; set; }
    Here's an example of my implementation :
    private string RenderPersonneEdition(object column, string type, PersonneDetailItem row)
    {
       return "some transformation happen here";
    }
      private void RenderDataTable()
    {  
    RenderDelegate renderPersonneEdition = (column, type, row) => RenderPersonneEdition(column, type, (PersonneDetailItem)row);
     var options = new Settings()
                {
                    lengthMenu = new Bridge.Union<double, string>[][] {
                        new Union<double, string>[] { "25", "50", "100" },
                        new Union<double, string>[] { "25", "50", "100" }
                    },
                    ajax = new AjaxSettings()
                    {
                        url = "someurl",
                        type = "Get",
                    },
                    columns = new ColumnSettings[] {
                        new ColumnSettings {
                            data = null,
                            title = "Actions",
                            render = renderPersonneEdition.ToDynamic(),
                            createdCell = createdCellPersonneEdition.ToDynamic(),
                            orderable = false,
                        },
                    },
                };
                datatables_net_Extensions.datatables_net(jQuery.select("#someid")).DataTable(options); }
    Is this implementation of the function render a good one ? What would the bridge.net team do ? What is the will behind this code generation ?

    #2
    Hi sacha,

    I agree that Union types are not really straightforward in terms of regular C# development - Union type supports the idea of polymorphism in JavaScript and TypeScript and that idea is quite different compared with C#. We keep spending significant efforts to make it more useful and clear, and at the same time to provide all benefits of static typing.

    As for lengthMenu property - this is how it's defined in the declaration file:
    lengthMenu?: (number | string)[] | (number | string)[][];
    So lengthMenu accepts values of one/two dimensional array type, each element of which could be either number or string. That API is wider than just int[][], making the following statements allowed (the last statement is a bit simplified code from you sample):
    lengthMenu = new Union<double, string>[] { 25, 50, 100};
    lengthMenu = new Union<double, string>[] { "str1", "str2"};
    lengthMenu = new Union<double, string>[] { 25, "str1" };
    lengthMenu = new[]
    {
        new Union<double, string>[] { 25, 50, 100 },
        new Union<double, string>[] { 25, 50, 100 }
    };
    I can't really suggest how that API could be optimized. I've been thinking about the following implicit operators simplifying conversion from/to arrays of Union, but C# doesn't allow to do that:
    public static extern implicit operator Union<T1, T2>[] (T1[] t);
    public static extern implicit operator Union<T1, T2>[] (T2[] t);
    If you have any ideas on how we could simplify the API and keep the same functionality, please let us know.

    Let's now look at the render function. I've picked the types it requires from the declaration file:
    render?: number | string | ObjectColumnRender | FunctionColumnRender;
    
    interface ObjectColumnData {
       _: string;
       filter?: string;
       display?: string;
       type?: string;
       sort?: string;
    }
    
    interface ObjectColumnRender extends ObjectColumnData {
    }
    
    interface FunctionColumnRender {
       (data: any, t: string, row: any, meta: CellMetaSettings): void;
    }
    Here again we have a property of Union type. It could accept either a number/string/ObjectColumnData value or a delegate represented by FunctionColumnRender type. It's actually a known issue for Retyped, when a delegate is represented by an interface in TypeScript (see issue #25). There are several way how we could deal with it, we'll try to address that soon. For now you could provide implementation using a class-inheritor:
    render = new FunctionColumnRenderDelegate(),
    // ...
    public class FunctionColumnRenderDelegate : datatables_net.DataTables.FunctionColumnRender
    {
        public override void Self(object data, string t, object row, datatables_net.DataTables.CellMetaSettings meta)
        {
            // some transformation happen here
        }
    }
    or you could define a constructor and an implicit operator to make it behaving more like a delegate type:
    render = new FunctionColumnRenderWrapper((data, s, row, meta) =>
    {
        // some transformation happen here
    }),
    // OR:
    render = (FunctionColumnRenderWrapper) RenderPersonneEdition,
    private string RenderPersonneEdition(object data, string t, object row, datatables_net.DataTables.CellMetaSettings meta)
    {
          return "some transformation happen here";
    }
    
    // ...
    public class FunctionColumnRenderWrapper : datatables_net.DataTables.FunctionColumnRender
    {
        [Template("{0}")]
        public extern FunctionColumnRenderWrapper(FunctionColumnRenderDelegate fn);
    
        public static extern implicit operator FunctionColumnRenderWrapper(FunctionColumnRenderDelegate fn);
    
        [Template("{this}({0}, {1}, {2}, {3})")]
        public override extern void Self(object data, string t, object row, datatables_net.DataTables.CellMetaSettings meta);
    
        public delegate void FunctionColumnRenderDelegate(object data, string t, object row, datatables_net.DataTables.CellMetaSettings meta);
    }
    The last comment I'd like to add is regarding the last line of your sample:
    // Current:
    datatables_net_Extensions.datatables_net(jQuery.select("#someid")).DataTable(options); }
    
    // Revised (make sure you have "using Retyped"):
    jQuery.select("#someid").datatables_net().DataTable(options);
    Hope that helps.
    Last edited by Andrey; 2018-03-13 @ 03:51 PM.

    Comment


      #3
      Hello @Andrey,

      Thank you for your response :-)

      For Union, it's sad we can't make it clearer. It may be difficult for new people to understand they explicitly need to write .Union.
      What you show and that can't be done is also how I would have want it. Too bad.

      For the render function, I also tried what you wrote, by extending the function, but it doesn't seem to work. I don't know if it the Retyped implementation or the Typescript definition that may be wrong. I think it's the latter since the typescript definition seem to be made by the community.
      It's possible that the Typescript definition wrote by the community have a or more bug/s, which would then translate to the Retyped package.
      Is there any to add an "Official" tag on the Retyped packages to know where they come from ? (I know there's a link to the github)
      I'm thinking it will be hard to guess where come the problems :

      my implementation => the Retyped package => the Typescript definition => the javascript library

      And thank you for you last comment, I'm going to correct that right away !

      Comment


        #4
        I've created a Deck sample for render function prototype. It demonstrates the suggested approaches. Please pay your attention that I slightly modified the initial sample, e.g. for the sample with class-inheritor I added a constructor with a proper template (see line 43).
        https://deck.net/6258cbc540b18ea97285768c3afe6260

        If nothing from those 3 approaches works for you, then I'd say the issue is in the API matching. Your thoughts regarding TypeScript definitions are correct, most of them are built by the community, so errors are possible (in this case the declaration should be fixed first, then we could regenerated the Retyped package). I like your idea with "Official" label, for now you can follow by the Source url (pointing to a d.ts file) and see where it will navigate you - if it is an official NPM package or an official repo, then the declaration file is officially supported.

        Another idea we can check - make sure you use the same library version, that the declaration file was created for. It should be 1.10.9 based on the header info.

        If nothing helped, and you know what JavaScript output is expected for that scenario - you can post it here and we'll try to come up with the corresponding C# code.





        Comment


          #5
          A quick update - we implemented several enhancements into delegate types (see issue #25 for more details).
          Such types as FunctionColumnRender will be emitted as delegate types.

          The package will be updated in the upcoming release.


          Comment


            #6
            Thank you Andrey, I will try it when it's out !

            Comment

            Working...
            X