0

Feel like I'm somewhat close, but not quite there. I have a GridView that contains a LinkButton and Button. I have a site that needs to execute a stored procedure based on the gridview row index to pull data to a hidden textbox, then copy the value to a clipboard, so this requires serverside action followed by clientside action.

I feel like the javascript portion around the button is incorrect, because there can be multiple rows of these buttons.

The LinkButton contains the OnClientClick event that executes the JavaScript. The JavaScript then needs to execute the OnClick event of the Button, but I believe I need both the ClientID (which I have) and the row index of the button to properly execute the codebehind.

GridView sample:

<asp:LinkButton ID="lbtnCopy" runat="server" Text="Copy" style="float:right" OnClientClick="copyToClipboard()"></asp:LinkButton>
<input type="button" ID="btnSample" value="" style="display:none"   OnClick="Btn_copyWord" />

JavaScript function:

<script src="https://code.jquery.com/jquery-1.12.2.min.js"></script>
    <script type="text/javascript">

        function copyToClipboard() {
            document.getElementById('<%=btnSample.ClientID%>').click();
  

                var id = "#" + "<%= txtText.ClientID %>";
                try {
                    $(id).select();
                    document.execCommand("copy");
                }
                catch (e) {
                    alert('Copy operation failed');
                }
            }
     
    </script>

CodeBehind Function for the OnClick (Removed Certain Parts):

protected void Btn_copyWord(object sender, EventArgs e)
        {
            GridViewRow Row = ((GridViewRow)((Control)sender).Parent.Parent);
            string id = gvSubDetails.DataKeys[Row.RowIndex].Value.ToString();
            
       
            using (###)
            {
                using (###)
                {
                   ####
                   ####
                    sqlCon.Open();

                    SqlDataAdapter da = new SqlDataAdapter(cmd);
                    DataTable dt = new DataTable();
                    da.Fill(dt);
                    if (dt.Rows.Count > 0)
                    {
                        txtText.Text = dt.Rows[0].Field<String>(0);                  
                    }
                    else
                    {

                    }
                    sqlCon.Close();
                }
            }
        }

1 Answer 1

1

You not at all made the case you need two buttons.

And you not at all stated why this row click data that you want to copy into the paste buffer can't be included in each row. And since it can be included in each row, then you don't need to run any server side code here.

So, let's assume a simple gridview. And say we want to click on a button on a row, and have some data from that row be copied into your paste buffer.

And VERY little reason to call server-side information UNLESS that information is not displayed in the current row and cannot be (and to be MORE specific, that data cannot be included in the row of data - even if not to be dispalyed in the gv, as long as that data is PART OF the row data source, we can get/use/enjoy that data in our client side click event).

Then REALLY to suggest that data can't be included in the current row on grid render then, right???

Let's create a simple gv. And then drop in a button and use a client side click event for this.

Our gv and markup is thus this:

And we ONLY need to drop in a plane jane regular aspnet button.

<asp:GridView ID="GridView1" 
    runat="server" CssClass="table" AutoGenerateColumns="false"
    width="42%" DataKeyNames="ID" >
    <Columns>
        <asp:BoundField DataField="FirstName" HeaderText="FirstName"  />
        <asp:BoundField DataField="LastName" HeaderText="LastName"    />
        <asp:BoundField DataField="HotelName" HeaderText="Hotel Name"    />
        <asp:BoundField DataField="Description" HeaderText="Description" ItemStyle-Width="270" />
        <asp:TemplateField HeaderText="Edit">
            <ItemTemplate>
                <asp:Button ID="cmdEdit" runat="server" Text="Copy!" 
                    CssClass="btn" 
                    MyHotelName = '<%# Eval("HotelName") %>'
                    OnClientClick="MyCopy(this);return false;"
                    />
            </ItemTemplate>
        </asp:TemplateField>
    </Columns>
</asp:GridView>

<br />

<script>
    function MyCopy(btn) {

        mytext = $(btn).attr("MyHotelName")

        navigator.clipboard.writeText(mytext).then(function () {
            console.log('Copy to clipboard was successful!');
        }, function (err) {
            console.error('Could not copy text: ', err);
        });
    }
</script>

And code behind:

    protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
            LoadGrid();
    }

    void LoadGrid()
    {
        using (SqlConnection conn = new SqlConnection(Properties.Settings.Default.TEST4))
        {
            string strSQL = "SELECT * FROM tblHotelsA ORDER BY HotelName";

            using (SqlCommand cmdSQL = new SqlCommand(strSQL, conn))
            {
                DataTable rstData = new DataTable();
                conn.Open();
                rstData.Load(cmdSQL.ExecuteReader());
                GridView1.DataSource = rstData;
                GridView1.DataBind();
            }
        }
    }

And now we have this:

enter image description here

so, click on any row copy! button, and the hotel name will be in the browsers clipboard/paste buffer.

You can of course replace our custom attribute with other column values - even values that don't appear in the gv column list for display, but any valid column from the binding datasource that is being feed into the gv can be used here.

Edit: user needs PK row ID from database

Ok, so we not looking to pull/use existing data, but get the database row PK id, and then generate some key or value or walk the dog.

So, our button becomes this:

                <asp:Button ID="cmdEdit" runat="server" Text="Copy!" 
                    CssClass="btn" 
                    OnClientClick = '<%# "MyCopy(" + Eval("ID") + ");return false" %>'
                    />

And now, the js routine becomes this:

<script>
    function MyCopy(id) {
    // do a web service call, or whatever to get key value
    // code to put value into paste buffer


    
  
Sign up to request clarification or add additional context in comments.

3 Comments

So, unfortunately data does need to be pulled from the code behind on button press, as the data is hidden an encrypted (Password information). It cannot be displayed in the gridview in plaintext. So the desire is to have a user press the copy button, have the SQL query retrieve the information to a hidden location, and then have it copied to the clipboard.
Ok, so in place of passing "this" (the button) to the js routine, then pass the row pk value. From that you make a web service call, and return your key value (or whatever), and then shove that value into clipboard. Note how my code allows use of a varible, and you realy don't have to have a hidden field/text box. So, you probably make a webmethod call - as tht makes the most sense unless a post-back is ok, but I vote for a webmthod call to some code behind in that given web page to return the key you need.
so, see my edit - pass the PK row id, and then you can make a webmethod call to get your key.

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.