2

My code generates a table with a button at the end of each row. When the user clicks a button how can I pass a property u.userEmail to the controller via the button? Will the value being sent to the controller be a string?

My (non-working) attempt:

    <script>

        $(document.body).append("waiting on async table to load<br>");

        $(document).ready(function () {
            $.getJSON("/Account/LoadClaimsTable", function (crewResponse) {
                //returns a List<UserClaims>
                $(document.body).append("<table>")
                crewResponse.forEach(function (u) {
                    var s = "";
                    s+="<tr><td>" + u.userEmail + "</td>";
                    u.userClaims.forEach(function (k) {
                        console.log("added claim"+k.value);
                        s += ("<td>" + k.type + "</td><td>" + k.value + "</td><td>" +
                            "<input type=\"hidden\" name=\"userEmail\" value=\"`${u.userEmail}`\" />"+
                            "<input type=\"button\" value=\"Create\" onclick=\"location.href='@Url.Action("EditClaims", "Account")'" />
+"</td>");
                    });
                    s += "</tr>";
                    $(document.body).append(s);
                    s = "";
                });
                $(document.body).append("</table>")
            });
        });
    </script>

AccountController.cs contains:

    public ActionResult EditClaims(string userEmail)
    {
        return View("StringView", userEmail);
    }
2
  • How does the EditClaims method signature looks like ? Does it have a param for email ? Commented Apr 9, 2018 at 19:06
  • @Shyju updated my code with the method signature. Let me know if any more code would be useful Commented Apr 9, 2018 at 19:08

3 Answers 3

1

You have to pass it on the url of the action. Not sure if you want to pass u.userEmail, but it could looks like this:

crewResponse.forEach(function (u) { 
    var s = "<tr><td>" + u.userEmail + "</td>";
    u.userClaims.forEach(function (k) {
        console.log("added claim"+k.value);
        s += ("<td>" + k.type + "</td><td>" + k.value + "</td><td>" +
            "<input type=\"hidden\" name=\"userEmail\" value=\"`${u.userEmail}`\" />"+
            "<input type=\"button\" value=\"Create\" onclick=\"location.href='@Url.Action("EditClaims", "Account")?userEmail=" + u.userEmail + "'\"/></td>");
    });
    s += "</tr>";
    $(document.body).append(s);
});
Sign up to request clarification or add additional context in comments.

Comments

0

There are multiple ways to do it. One is mentioned in the answer above by Felipe. Here is another alternate approach using unobtrusive js

Add the email as html5 data attributes to the button along with another attribute which we will use bind the click behavior.

u.userClaims.forEach(function (k) {
     // Add quotes as needed if you want multiline ( i just removed those)

     s += "<td>" + k.type + "</td><td>" + k.value + "</td><td>
           <input type='button' 
           clickablebutton data-email='" + u.email + "' value='Create'/></td>";
});

Now, in your document ready, bind a click event handler to those elements (with our custom attribute) and read the data attribute and build the url you need.

$(document).on("click", "input[clickablebutton]", function (e){

    var url = '@Url.Action("EditClaims", "Accounts")?useremail=' + $(this).data("email");
    window.location.href = url;

});

Some other suggestions

  1. Use the appropriate element. Button is better than input (Consider accessibility)
  2. If it is for navigation, Use an anchor tag instead of a button.
  3. Inline javascript is not great. Let the browser parses your markup without any interruptions and you can add the behavior scripts later (that is the whole point of uobutrisive js approach)

Comments

0

The approach you appear to be taking would be Ajax, response, render a template. With that being said, you may want to rethink your approach.

Step 1.

Build a template

<template id="...">
     <button type="button" value="[action]" onclick="[url]">[text]</button>
</template>

Step 2.

Create your request.

axios.get('...').then((response) => {
     // Retrieve template.
     // Replace bracket with response object model data.
     html += template.replace('[action]', response.action);
});

Step 3.

Have the JavaScript render your template.

The above can create a clear concise codebase that is easier to maintain and scale as the scope changes, rather than an individual request performing a change with embedded markup. This approach has worked quite well for me, also I feel it'll make you troubleshooting and definition easier, as the controller is handing an object back to your JavaScript instead of a markup / view data. Which will be a better finite control for the frontend and clear modifications in future.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.