Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Actions with fields instead of plain html #375

Closed
wants to merge 28 commits into from
Closed

Actions with fields instead of plain html #375

wants to merge 28 commits into from

Conversation

hasansezertasan
Copy link
Contributor

@hasansezertasan hasansezertasan commented Nov 3, 2023

There are certain times when my actions have a bunch of inputs... Writing plain HTML for those inputs doesn't seem right since we have a field system which is awesome and somewhat similar to WTForms.

It doesn't work properly on some fields like RelationField and BooleanField. I will work on those when/if this PR gets merged.

What are your thoughts?

@hasansezertasan
Copy link
Contributor Author

I figured it out why RelationField doesn't work... None of the "JavaScript initialized" fields work because the initialization is triggered when the page has been loaded, not when someone clicks an action.

I believe we need to wait for #444 to be resolved before merging this, and we should turn the processElement function inside form.js into a global function instead of a self-calling function.

Note: You might ask "What do you mean by self-calling function", I don't know what JS people call this:

(function () {
    function processElement(element) {
        // Logic
    }
    $(function () {
      processElement(document);
    });
  })();

By self-calling, I'm referring processElement function, which we can not call after the script runs. And by global function, I meant a function that you can call anywhere on the page.

@hasansezertasan
Copy link
Contributor Author

I figured it out why RelationField doesn't work... None of the "JavaScript initialized" fields work because the initialization is triggered when the page has been loaded, not when someone clicks an action.

I have found two solutions for this:

  • Add script path to your form string manually:
    @row_action(
        name="action",
        text="My Action",
        confirmation="Are you sure?",
        form="""
        <form>
        </form>
        <script type="text/javascript" src="/admin/statics/js/form.js"></script>
        """,
    )
  • Customize actions.js like this:
  /**
   * Initialize actions that trigger a modal dialog for user confirmation.
   */
  initActionModal() {
    let self = this;
    $("#modal-action").on("show.bs.modal", function (event) {
      let button = $(event.relatedTarget); // Button that triggered the modal
      let confirmation = button.data("confirmation");
      let form = button.data("form");
      let name = button.data("name");
      let submit_btn_text = button.data("submit-btn-text");
      let submit_btn_class = button.data("submit-btn-class");
      let customResponse = button.data("custom-response") === true;
      let isRowAction = button.data("is-row-action") === true;

      let modal = $(this);
      modal.find("#actionConfirmation").text(confirmation);
      let modalForm = modal.find("#modal-form");
      modalForm.html(form);
      let actionSubmit = modal.find("#actionSubmit");
      actionSubmit.text(submit_btn_text);
      actionSubmit.removeClass().addClass(`btn ${submit_btn_class}`);
      actionSubmit.unbind();
      actionSubmit.on("click", function (event) {
        const formElements = modalForm.find("form");
        const form = formElements.length ? formElements.get(0) : null;
        self.submitAction(name, form, customResponse, isRowAction, button);
      });
      let scriptEle = document.createElement("script");
      scriptEle.setAttribute("src", "/admin/statics/js/form.js");
      document.body.appendChild(scriptEle);
      scriptEle.addEventListener("load", () => {
        console.log("File loaded")
      });
      scriptEle.addEventListener("error", (ev) => {
        console.log("Error on loading file", ev);
      });
    });
  }

This is the tutorial that helped me achieve this: How to dynamically load a JS file in JavaScript

I don't think either way is the best, I believe starlette-admin should figure out if the form.js is required or not.

@hasansezertasan
Copy link
Contributor Author

Due to #505, I'm closing this one.

@hasansezertasan hasansezertasan deleted the actions-with-fields branch February 21, 2024 02:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants