0

I'm using JQuery on two input text elements (that are readonly) and two buttons so that when button 1 is clicked only input 1 should become read/write. And, when button 2 is clicked, only input 2 should become read/write. And when the corresponding button is clicked again the corresponding input should become readonly again. But my following script changes the readonly attribute of both the inputs no matter which button is clicked. I thought only one event should be fired for that particular input as explained here by a user here

NOTE: I know we can use id instead of class selector but in my real scenario the input and buttons tags are generated dynamically via a loop and the data comes from a database. Hence, we don't know how many such element would be created each time. And, as the user in the above mentioned link pointed out only one click event should be fired for a corresponding button. So the Question is really how we can achieve that scenario since the example given below is not going to work in such a scenario.

HTML:

<table>
    <tbody>
        <tr>
            <td>
                <input class="txtInput" type="text" name="test1" value="test1val" readonly/>
            </td>
            <td>
                <input type="button" class="btnEdit" name="editName" value="Edit"/>
            </td>
        </tr>
        <tr>
            <td>
                <input class="txtInput" type="text" name="test2" value="test2val" readonly />
            </td>
            <td>
                <input type="button" class="btnEdit" name="editName" value="Edit" />
            </td>
        </tr>
    </tbody>
</table>

JQuery:

$(document).ready(function () {
    $('.btnEdit').click(function () {
        if ($('.txtInput').prop('readonly')) {
            $('.txtInput').removeAttr('readonly');
        }
        else {
            $('.txtInput').attr('readonly', 'readonly')
        }
    });
});

Page display:

enter image description here

Community
  • 1
  • 1
nam
  • 21,967
  • 37
  • 158
  • 332

3 Answers3

3

You can target the previous TD of the clicked button, and find the input

$(document).ready(function () {
    $('.btnEdit').on('click', function () {
        $('table .txtInput').prop('readonly', true);
        var elem = $(this).closest('td').prev('td').find('.txtInput');
        elem.prop('readonly', function(_,state) { return !state });
    });
});
input[readonly] {color: red}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
    <tbody>
        <tr>
            <td><input class="txtInput" type="text" name="test1" value="test1val" readonly/></td>
            <td><input type="button" class="btnEdit" name="editName" value="Edit" /></td>
        </tr>
        <tr>
            <td><input class="txtInput" type="text" name="test2" value="test2val" readonly /></td>
            <td><input type="button" class="btnEdit" name="editName" value="Edit" /></td>
        </tr>
    </tbody>
</table>
adeneo
  • 312,895
  • 29
  • 395
  • 388
  • Your example make both the inputs editable once the other button is clicked. E.g: Clicking btn1 changes input1 tag to editable. Then clicking btn2 makes input2 tag editable; but the input1 tag remains editable also. – nam Jan 17 '17 at 21:48
  • @nam - I assumed that was the point, but if you only ever wanted to have one input active, just set the readonly property for all of them before you change it for the current one etc. Edited the answer. – adeneo Jan 18 '17 at 01:36
0

I'd code it slightly differently from adeneo. I'd go to the closest row and then find the text so something like this:

$(document).ready(function () {
    $('.btnEdit').on('click', function () {

        var elem = $(this).closest('tr').find('.txtInput');
        elem.prop('readonly', function(_,state) { return !state });
    });
});

Alternatively, you could have an attribute on the button have the id of the textbox you wanted to alter so the html would have to change to have ids:

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
    <tbody>
        <tr>
            <td><input class="txtInput" id='txt1' type="text" name="test1" value="test1val" readonly/></td>
            <td><input type="button" txtid='#txt1' class="btnEdit" name="editName" value="Edit" /></td>
        </tr>
        <tr>
            <td><input class="txtInput" id='txt2' type="text" name="test2" value="test2val" readonly /></td>
            <td><input type="button" txtid='#txt2' class="btnEdit" name="editName" value="Edit" /></td>
        </tr>
    </tbody>
</table>

and the javascript would be:

$(document).ready(function () {
    $('.btnEdit').on('click', function () {
        var txtid = $(this).attr('txtid');
        $(".txtInput").each(function(){
              if ($(this).attr('id')!=txtid)   
              {
                  $(this).prop('readonly',true);
              }
        });
        var elem = $();
        elem.prop('readonly', function(_,state) { return !state });
    });
});
MikeS
  • 1,734
  • 1
  • 9
  • 13
  • Your alternate method almost works with one exception: Once one button is clicked the state of the other button does not change. E.g: Clicking btn1 changes input1 tag to editable. Then clicking btn2 makes input2 tag editable; but the input1 tag remains editable also. – nam Jan 16 '17 at 20:39
0

I would set a custom data attribute for each button, in the following way:

       <td><input class="txtInput" type="text" id="test2" name="test2" value="test2val" readonly /></td>
        <td><input type="button" class="btnEdit" data-attr-target="test2" name="editName" value="Edit" /></td>

Then you could ask for that custom attribute in the click handler.

$('.btnEdit').click(function(){
    var target = $(this).data('attr-target');
    var input = $(target);
    input.attr('readonly', readonly);
});

You mentioned that these elements are generated dynamically. I see that's no issue for having dynamic ids. You may have an "inputName_index" like id when generating the inputs.

Federico Alecci
  • 914
  • 6
  • 14