NicolasCARPi / jquery_jeditable

jQuery edit in place plugin. Extendable via plugin architecture. Plugins for plugin. Really.
https://jeditable.elabftw.net
MIT License
1.74k stars 458 forks source link

$('.edit').editable() doesnt work in Partial View in ASP.NET MVC5 #210

Closed yizongk closed 4 years ago

yizongk commented 4 years ago

Description

in ASP.NET When you attempt to use Ajax to load in partial views, any element with \<div class='edit'> in the partial view is not able to be editable.

How to reproduce

Use Visual Studio and generate a general MVC 5 application, and in it's Home/Index, add a div for your partial view to be loaded into. Create a partial view, and use Ajax to load the partial view into Home/Index (Will provide some codes when I get the time)

Expected result

Partial View to be editable

Actual result

Partial View is not editable, nothing happens, it's as if it's a static page .

Environment

jQuery version: 3.4.1 Browser: Firefox Dev version 71.0b4 (64-bit) OS: Wins 10

NicolasCARPi commented 4 years ago

I'll let you update your issue with a codepen example ;)

yizongk commented 4 years ago

Hi!

Sorry, this isn't a bug, your jeditable library works just fine!

I found the problem! The problem is that I called $(.'edit').editable(...) in the wrong place. The way I have it now, I called $(.'edit').editable(...) when there isn't any \<div class='edit'> in Index.cshtml, because those \<div>s haven't been loaded in by AJAX, because the data is still loading from the back-end server. As part of a solution, I also have to re-call $(.'edit').editable(...) every time AJAX finishes loading in some new \<div>s. Solution is at the bottom.

The following is info for people who encounter the same problem (In ASP.NET MVC5).

My old setup: Scripts/local/main.js:

console.log("partial view jeditable loaded");
$(document).ready(function () {
      console.log("jeditable doc ready");
      $('.edit').editable('/Home/[your controller action that does something with what jeditable sends to it]');  
});

Views/Home/Index.cshtml:

@{
    Layout = "~/Views/Shared/_Layout.cshtml";
}
...
<div class="partialView" data-url=@ViewBag.PartialViewLink>EMPTY RIGHT NOW</div>   //This div will be replace with a Partial-View by AJAX, when server replies with some data to populated the Partial-View.
...

Views/Shared/_Layout.html: THE PROBLEM!

...
<body>
     ...
    <div class="container body-content">
        ...
        @RenderBody()   // Views/Home/Index.cshtml will be rendered here!
        ...
    </div>

    <script src="~/Scripts/local/jquery.jeditable.mini.js"></script>
    <script src="~/Scripts/local/main.js"></script>     //-> This was the problem. I called $(.'edit').editable(...) in main.js, when I should have called it in $(document).ajaxStop(function() { ...place it in here!... });
    @RenderSection("scripts", required: false)
</body>
...

Views/Home/IndexPartialView.cshtml:

...
<div id="webGrid">
    tableStyle: "table table-responsive table-striped table-bordered",
        columns: grid.Columns(
                        grid.Column(header: @Html.DisplayNameFor(model => model.Val).ToString(), format: @<text><div class="edit" data-id="@item.Record_ID" data-propertyname=@Html.DisplayNameFor(model => model.Val).ToString()>@item.Val</div></text>)
        )
</div>
...

The fix

move $(.'edit').editable(...) from wherever you have it, to the where you called your $(document).ajaxStop(...)

In my case, edit Scripts/local/main.js:

...
console.log("partial view jeditable loaded");
$(document).ready(function () {
      console.log("jeditable doc ready");
      // $('.edit').editable('/Home/[your controller action that does something with what jeditable sends to it]');  // MOVE THIS LINE
});
...
// ADD THE FOLLOWING
$(document).ajaxStop(
    function () {
        console.debug("debug: main.js: ajaxEnd triggered ");
        $('.edit').editable('/Home/[your controller action that does something with what jeditable sends to it]');
    },
);

And now I can edit in-line in the web-grid in the /Views/Home/IndexPartialView.cshtml! And paging functions of web-grid now works with jeditable!

Long story short:

Just make sure at the time your JavaScript runs, that anythings the JaveScript references, is already in the html file.

Any additional \<div>s added on by AJAX to the html file after the JavaScript is loaded, the JavaScript won't find it! Work around it by calling the same JavaScript codes after each AJAX requests, with:

$(document).ajaxStop( function() {  
    ... your javascript codes here ...  
} );

Don't be a newbie like me :^)

NicolasCARPi commented 4 years ago

Yes, it is an issue with this library, element needs to exist. For dynamic elements, I just call it again on it and it works.

Thanks for posting the detailed explanation, I'm sure it'll help someone somewhere... :)