How can I show a dynamically generated textarea on

2019-08-23 06:25发布

问题:

I want to show a text area based on a button click. Pretty simple, but the textarea and button are dynamically generated using Knockout js. My current code works, except it only expands the first text area. There are several projects displayed.

HTML (the button and textarea are the last two controls):

 <!-- ko foreach: projects -->
    <div id="eachOppyProject" style="border-bottom: 1px solid #eee;">
        <table>
            <tbody>
                <tr>
                    <td><a data-bind="attr: { href: '/tools/oppy/' + guid }" style="font-size: 25px;"><span class="link" data-bind="    value: guid, text: name"></span></a></td>
                </tr>
                <tr data-bind="text: projectDescription"></tr>
                <tr data-bind="text: guid"></tr>
            </tbody>
        </table>
        <span class="forminputtitle">Have you done project this before?</span>  
        <input type="button" id="oppyBtn" class="btnOppy" data-bind="click: toggleTextArea" value="Yes" />
        <textarea id="oppyDoneTextArea" placeholder="Tell us a little of what you've done." data-bind="visible: show" /><br />
    </div>
<!-- /ko -->

JavaScript:

function displayTextArea() {
    var my_disply = document.getElementById('oppyDoneTextArea').style.display;
    if (my_disply == "block")
        document.getElementById('oppyDoneTextArea').style.display = "none";
    else
        document.getElementById('oppyDoneTextArea').style.display = "block";
}

Knockout View Model:

    function ProjectViewModel(proj) {
        //console.log(proj);
        var self = this;
        self.projects = ko.observableArray(proj);
var project = function(){
    var self = this;
    self.show = ko.observable(false);
    self.toggleTextArea= function(){
        self.show(!self.show());
        };
      }; 
    };

As you can see, the controls are dynamically generated based on the objects that Knockout binds. So, using ID's is a bad idea because it would generate duplicate IDs. That is currently my problem now -- this code works for the first text area but doesn't work for the rest of the projects that display.

回答1:

I would try creating 2 properties on the project model, 'show' and 'toggleTextArea':

<!-- ko foreach: projects -->
<div id="eachOppyProject" style="border-bottom: 1px solid #eee;">
    <table>
        <tbody>
            <tr>
                <td><a data-bind="attr: { href: '/tools/oppy/' + guid }" style="font-size: 25px;"><span class="link" data-bind="    value: guid, text: name"></span></a></td>
            </tr>
            <tr data-bind="text: projectDescription"></tr>
            <tr data-bind="text: guid"></tr>
        </tbody>
    </table>
    <span class="forminputtitle">Have you done project this before?</span>  
    <input type="button" id="oppyBtn" class="btnOppy" value="Yes" data-bind="click: toggleTextArea" />
    <textarea id="oppyDoneTextArea" placeholder="Tell us a little of what you've done." style="height:75px;" data-bind="visible: show" /><br />
</div>
<!-- /ko -->

your project model could be something like this:

var project = function(){
    var self = this;
    self.show = ko.observable(false);
    self.toggleTextArea= function(){
        self.show(!self.show());
    };
}; 

This allows the click of the button to toggle the status of the textarea.



回答2:

I think you ca try this to get the result.

HTML (the button and textarea are the last two controls):

<!-- ko foreach: projects -->
    <div id="eachOppyProject" style="border-bottom: 1px solid #eee;">
        <table>
            <tbody>
                <tr>
                    <td><a data-bind="attr: { href: '/tools/oppy/' + guid }" style="font-size: 25px;"><span class="link" data-bind="    value: guid, text: name"></span></a></td>
                </tr>
                <tr data-bind="text: projectDescription"></tr>
                <tr data-bind="text: guid"></tr>
            </tbody>
        </table>
        <span class="forminputtitle">Have you done project this before?</span>  
        <input type="button" id="oppyBtn" class="btnOppy" onclick="displayTextArea(this)" value="Yes" />
        <textarea id="oppyDoneTextArea" placeholder="Tell us a little of what you've done." style=" display:none; height:75px; " /><br />
    </div>
<!-- /ko -->

JavaScript:

function displayTextArea(element) {
    var my_disply = element.nextSibling
    if (my_disply == "block")
        document.getElementById('oppyDoneTextArea').style.display = "none";
    else
        document.getElementById('oppyDoneTextArea').style.display = "block";
}

Hope it will help you and will work only when the textarea is the next sibling to button on clicking of which you have to show the textarea