Using stand alone editor without a data_editor_id

Using stand alone editor without a data_editor_id

OudalallyOudalally Posts: 17Questions: 4Answers: 0
edited April 2023 in Free community support

I'm using the editor in stand alone mode to edit fields in a calendar component.
The editor is loading as expected, and I'm making an ajax call to retrieve the appropriate row from the db table and populating the fields in the editor form.
When saving, the tow is updated correctly, however it throws an error that there is no id or data_editor_id set.

Due to the nature of the calendar component, there is no simple way to provide an id for an event on the calendar to allow the editor to update the values, however I have added a postEdit function which reloads the records from the DB (it's overkill, but it's a fairly quick operation and works well enough for this purpose).

Is there a way to prevent the editor from trying to update anything once it's saved the row, and simply allowing it to close. At this point, the refresh will run fine.

This behaviour works prefectly well when creating a new item using the same method, but the edit is causing me some issues.
I have included the function I'm using to launch the editor below. It is triggered from a click on a context menu.

Any help would be very much appreciated.

 text: "Edit", onClick: (args) => {
    var selectedId = args.source.id();
    editor.on('postEdit', function (e, json) {
        console.log("Edit operation finished");
        month.events.load("./controllers/calendar/calendar-month-provider.php");
    });

    $.ajax({
        url: 'controllers/restrictions-dt-provider.php',
        data: {
            id: selectedId
        },
        dataType: 'json',
        success: function (json) {
            console.debug(json);
            let data = json.data[0];
            editor
                .title('Create Booking Restriction')
                .buttons('Save')
                .edit(selectedId)
                .val('campervan_tent', data.campervan_tent)
                .val('motorhome', data.motorhome)
                .val('caravan', data.caravan)
                .val('date_from', data.date_from)
                .val('date_to', data.date_to)
                .val('note', data.note);
        }
    });
   }

This question has an accepted answers - jump to answer

Answers

  • allanallan Posts: 63,523Questions: 1Answers: 10,473 Site admin

    Hi,

    Thanks for your question. Couple of questions: Are you able to give me a link to the page so I can take a detailed look at the issue? If not, can you show me your Editor initialisation please? Also, can you show me the exact error message that is being given?

    Thanks,
    Allan

  • OudalallyOudalally Posts: 17Questions: 4Answers: 0
    edited April 2023

    The project is for a client, so there's no easy way to give you access to the repo I'm afraid, however, I can show you how I'm initialising the editor.

    I'm initialising the editor with the following function which is called from document ready.

    var editor;
    
    function initDataEditor() {
        editor = new DataTable.Editor({
            ajax: "controllers/restrictions-dt-provider.php",
            fields: [
                {
                    "label": "Campervan/Tent:",
                    "name": "campervan_tent"
                },
                {
                    "label": "Motor Home:",
                    "name": "motorhome"
                },
                {
                    "label": "Caravan:",
                    "name": "caravan"
                },
                {
                    "label": "From:",
                    "name": "date_from",
                    "type": "datetime",
                    "format": "dd/MM/yyyy"
                },
                {
                    "label": "To:",
                    "name": "date_to",
                    "type": "datetime",
                    "format": "dd/MM/yyyy"
                },
                {
                    "label": "Note:",
                    "name": "note",
                    "type": "textarea"
                }
            ]
        });
    }
    

    In the context menu handler for items on the calendar component (I'm using the lite version of DayPilot in Month view), I have the following handler which is invoking the editor.

    {
                        text: "Edit", onClick: (args) => {
                            var selectedId = args.source.id();
    
                            editor.on('postEdit', function (e, json) {
                                console.log("Edit operation finished");
                                month.events.load("./controllers/calendar/calendar-month-provider.php");
                            });
    
                            $.ajax({
                                url: 'controllers/restrictions-dt-provider.php',
                                data: {
                                    id: selectedId
                                },
                                dataType: 'json',
                                success: function (json) {
                                    console.debug(json);
                                    let data = json.data[0];
                                    editor
                                        .title('Create Booking Restriction')
                                        .buttons('Save')
                                        .edit(selectedId)
                                        .val('campervan_tent', data.campervan_tent)
                                        .val('motorhome', data.motorhome)
                                        .val('caravan', data.caravan)
                                        .val('date_from', data.date_from)
                                        .val('date_to', data.date_to)
                                        .val('note', data.note);
                                }
                            });
                        }
                    }
    

    The error message being thrown is Error: Could not find an element with `data-editor-id` or `id` of: row_1 - though this message varies, and the id reflects the actual row id from the table in the DB. Last night, it was row_8 that was complaining.

    All I can think of currently is that I'm causing the issue by having my definition for the postEdit function inside mmy click handler, but this is really grasping at straws.

    I'm a C++ dev most of the time and for the past few years I've been working almost entirely in immediate mode guis, so I'm really out of my comfort zone here.

    Thank you for your help, it is very much appreciated.

  • allanallan Posts: 63,523Questions: 1Answers: 10,473 Site admin

    Perfect - thank you. Editor, in standalone mode, makes an assumption that if you pass in an id then it should do updates to the document based on that id. That allows things like this example to be produced.

    You've got me wondering if that is needed - I could perhaps just do nothing if no matching element is found...

    In the short term, what you could do is simply call .edit() without passing anything in (since you are setting all the values yourself anyway, they aren't being read from the document).

    If you need the selectedId, then you could pass that as another field (I'm assuming that you aren't using our Editor PHP libraries here)?

    Allan

  • OudalallyOudalally Posts: 17Questions: 4Answers: 0

    Hi Allan.

    In this case, I am indeed using your Editor PHP libraries. The selectedId is coming from the calendar component, and corresponds to the ID field in the database table.

    The reason I passed it in to the editor is so that saving it can update that same row, which indeed it is doing, however I might very well have misunderstood whether this is necessary.

    If I'm passing in the ID from the JSON which is coming back from the query, will that be used to update the row?
    If so, I can do away with passing in the parameter.

    My reason for passing the values in having loaded them via ajax is purely so that the current values are displayed on the form.

    I'll have a play with it now and see what happens.
    Many thanks indeed!

  • OudalallyOudalally Posts: 17Questions: 4Answers: 0

    Hmmmm...

    It appears that I have an issue elsewhere as my JSON is returning records where they shouldn't be. It ought to be selecting based on the ID, but it is instead returning all the rows for that month.

    I think I need to dig into this further. When I initially was testing it, there was only one item in the table and I assumed (a stupid thing to do in development I know) that this was down to the ajax query filtering the results.

    It seems that this is not the case.
    restrictions-dt-provider.php is creating an Editor instance as shown below. Is it possible to add a restriction in my ajax call to only bring back a single record matching the ID I'm looking for, or will I need to loop through the data object returned by the ajax call and find the matching element for this record?

    Thanks again for your help. I've pulled a lot of late nights trying to get this finished, and I think the tiredness is catching up with me now.

    Editor::inst( $db, 'booking_restrictions' )
        ->fields(
            Field::inst( 'id' )
                ->validator( Validate::numeric() )
                ->setFormatter( Format::ifEmpty(null) ),
            Field::inst( 'campervan_tent' )
                ->validator( Validate::numeric() )
                ->setFormatter( Format::ifEmpty(null) ),
            Field::inst( 'motorhome' )
                ->validator( Validate::numeric() )
                ->setFormatter( Format::ifEmpty(null) ),
            Field::inst( 'caravan' )
                ->validator( Validate::numeric() )
                ->setFormatter( Format::ifEmpty(null) ),
            Field::inst( 'date_from' )
                ->validator( Validate::dateFormat( 'd/m/Y' ) )
                ->getFormatter( Format::dateSqlToFormat( 'd/m/Y' ) )
                ->setFormatter( function ($val, $data) {
                    $dtWithTime = $val . " 00:00:00";
                    $parsedDate = date_create_from_format("d/m/Y H:i:s", $dtWithTime);
                    return date_format($parsedDate, "Y-m-d H:i:s");
                }),
            Field::inst( 'date_to' )
                ->validator( Validate::dateFormat( 'd/m/Y' ) )
                ->getFormatter( Format::dateSqlToFormat( 'd/m/Y' ) )
                ->setFormatter( function ($val, $data) {
                    $dtWithTime = $val . " 23:59:59";
                    $parsedDate = date_create_from_format("d/m/Y H:i:s", $dtWithTime);
                    return date_format($parsedDate, "Y-m-d H:i:s");
                }),
            Field::inst( 'note' )
        )
        ->debug(true)
        ->process( $_POST )
        ->json();
    
  • OudalallyOudalally Posts: 17Questions: 4Answers: 0

    Right, that JSON issue is now sorted.

    When I don't pass a value into the edit() call, it is populating the form but treating it as a create operation, and I get an sql error as it's trying to insert the value 'keyless' into the ID column.

  • OudalallyOudalally Posts: 17Questions: 4Answers: 0

    Ok, I've worked around it.
    I initially tried to add an element to the page with the id of data-editor-id, but that failed.

    So, I have added a div to the page...

    <div id="editor_field_container">
    </div>
    

    And in my click handler function before I actually launch the editor, I have created a script that clears the content of my new div, then creates a span with no content, and an id which matches the row id of the record I'm editing.

    var selectedId = args.source.id();
    var containerDiv = document.getElementById("editor_field_container");
    containerDiv.replaceChildren();
    var newRowSpan = document.createElement('span');
    newRowSpan.id = "row_" + selectedId;
    containerDiv.append(newRowSpan);
    

    It's a bit hacky, but it's done the trick.

  • allanallan Posts: 63,523Questions: 1Answers: 10,473 Site admin
    Answer ✓

    Yes, if you are using our libraries, you'd need to pass in the id being edited - it wouldn't pick it up from a hidden field.

    Your workaround is spot on at the moment. I will look into relaxing the HTML requirement constraint in Editor - I think that would be a good addition.

    Allan

Sign In or Register to comment.