Update LiveView html form before sending (implement reCAPTCHA v3 )

Hello, folks,

I want to implement Google reCAPTCHA V3 with phoenix LiveView help then I did this:

add Google js url:

<script defer phx-track-static  type="text/javascript" src="https://www.google.com/recaptcha/api.js?render=MY_CODE"></script>

Then I create a hook like this:

function onClick() {
  grecaptcha.ready(function() {
    grecaptcha.execute('MY_CODE', {action: 'submit'}).then(function(token) {
        document.getElementById("g-recaptcha-response").value = token;
        console.log(token)
    });
  });
}

Hooks.GooglereCAPTCHA = {
  mounted() {
    this.handleEvent("update_recaptcha", ({value}) => {
      onClick()
    });
  }
}

After this, I added it to my form header:

<%= f = form_for @changeset, Routes.auth_path(@socket, :login),
            phx_submit: "save",
            phx_change: "validate",
            id: "ClientLoginForm",
            phx_hook: "GooglereCAPTCHA",
            phx_trigger_action: @trigger_submit %>

Adding hidden fields is the next step before submit

<input type="hidden" id="g-recaptcha-response" name="g-recaptcha-response">

It is time to change the “save” function before trigger form:

  @impl true
  def handle_event("save", %{"user" => params}, socket) do
    filtered_params = Map.merge(params, %{"email" => MishkaHtml.email_sanitize(params["email"])})
    changeset = user_changeset(filtered_params)

    socket =
      socket
      |> push_event("update_recaptcha", %{})
      |> assign(
        changeset: changeset,
        trigger_submit: changeset.valid?
      )
    {:noreply, socket}
  end

I can see my field is updated, but I think after sending form to my controller, and always I receive empty field on controller side

"g-recaptcha-response" => ""

I would appreciate your help in implementing this.


To complete this code, I also need to know how to use e.preventDefault(); on my onClick code. I am unable to use it in my app.js file

Google document code:

   <script>
      function onClick(e) {
        e.preventDefault();
        grecaptcha.ready(function() {
          grecaptcha.execute('reCAPTCHA_site_key', {action: 'submit'}).then(function(token) {
              // Add your logic to submit to your backend server here.
          });
        });
      }
  </script>

reference:

Thanks.

Tested several times, I discovered, my form is updated in JS file, but my LiveView form (phx_trigger_action) skips it and does not send hidden form value which is recreated

How can I fix this?

I have read these posts, but I couldn’t fix this

I can’t believe that I just need to replace phoenix hidden field instead of normal HTML field and put it on schema name list

<input type="hidden" id="g-recaptcha-response" name="g-recaptcha-response">

to

<%= hidden_input(f, :"g-recaptcha-response", id: "g-recaptcha-response")%>

My whole day was wasted :nauseated_face: :sob: :sob:

3 Likes