Вызов javascript от кнопки в HTML, созданной Javascript - PullRequest
0 голосов
/ 27 августа 2018

У меня есть проект Ruby on Rails (возможно, не относящийся к делу) с таблицей, которая генерируется java / coffescript.

В одном из полей этой таблицы есть кнопка, которую я хочу вызвать другой функцией JavaScript.

Я смотрел на Использование кнопки HTML для вызова функции JavaScript , но, похоже, не удается найти функцию "doFunction" ...

В настоящее время у меня есть:

class App.Table extends Backbone.Model
  defaults: {
    showPastResults: true
  }

  initialize: ->
    @set("selectedCohortLabel", @get("cohortLabels")[0])

  headers: =>
   [BLAH BLAH BLAH]

  columns: =>
    columns = []

    [BLAH BLAH BLAH]
    Array::push.apply columns, [['<input id="clickMe" type="button" value="clickme" onclick="doFunction();" />', 5, 5]]    if @get('haveDataBytes')
    columns

  doFunction: ->
    console.log("foo")

и я также пытался поставить doFunction вне класса. Это всегда дает:

420450:1 Uncaught ReferenceError: doFunction is not defined
    at HTMLInputElement.onclick (420450:1)
onclick @ 420450:1

Так где же должен жить doFunction, чтобы он мог найти его во время выполнения?

1 Ответ

0 голосов
/ 29 сентября 2018

Ваш подход не совсем соответствует архитектуре Backbone. В Магистрали ты смоделируйте свою бизнес-область как Модели и Коллекции Моделей. Если вы следуете В этом правиле все становится на свои места довольно красиво.

Решение назвать вашу модель Table неверно в этом контексте, так как таблица представительский объект. Сами данные могут отображаться разными способами.

Ниже приведен пример того, как приложение может (или должно) быть разработано в способ, который не работает против Backbone.js. Данные моделируются как коллекция элементов, каждый элемент будет представлен в строке таблицы. Пожалуйста, следуйте комментариям в исходном коде для дальнейшего объяснения.

Файл: index.html (я создаю приложение, используя npm и browserify, который не показано здесь. Обязательно укажите необходимые зависимости).

<!doctype html>
<html>
    <head>
        <title>Coffeescript And Backbone</title>
        <link rel="stylesheet" href="style.css">
    </head>
    <body>
        <div class="container">
            <h2>Elements Table</h2>
            <div class="table"></div>
        </div>

        <script id="tablerow" type="text/x-handlebars-template">
            <td>{{id}}</td>
            <td>{{name}}</td>
            <td>{{value}}</td>
            <td><button class="button">HaveDataBytes</button></td>
        </script>

        <script src="app.js"></script>
    </body>
</html>

Файл: app.coffee

# The template is integrated in index.html (script#tablerow).
# Here I read and compile the template function for the table row.
#
# This must be called after the template script is in the DOM.
#
# Using a packaging tool like browserify or webpack would allow you
# to precompile the templates during the packaging process, but this
# approach is good for small applications.
compileTemplate = (name) ->
    source = document.getElementById(name).innerHTML
    Handlebars.compile(source)

rowTemplate = compileTemplate('tablerow')

# Define the applications backbone
App =
    View: {}
    Model: {}
    Collection: {}

# This is a dummy dataset of elements that would be fetched from the server
# using the Collection abstraction. Each entry in data will be represented
# in a table view further down.
data = [
    { id: 1, name: "element1", value: "value1", haveDataBytes: true },
    { id: 2, name: "element2", value: "value2", haveDataBytes: false },
    { id: 3, name: "element3", value: "value3", haveDataBytes: true },
    { id: 4, name: "element4", value: "value4", haveDataBytes: true },
    { id: 5, name: "element5", value: "value5", haveDataBytes: false }
]

# The model element takes up each entry from data ...
class App.Model.Element extends Backbone.Model

# and is stored in a collection of Element models
class App.Collection.Elements extends Backbone.Collection
    model: App.Model.Element

По сравнению с вашим подходом с простыми списками для заголовков и столбцов в модели Основным преимуществом является то, что все данные хранятся и контролируются Backbone. Вы можете просто обновить всю коллекцию, прослушать изменения и отправить события, сериализовать отдельные записи на сервер, реагировать на изменения отдельных записей - полный контроль ...

# The table view
class App.View.ElementsTable extends Backbone.View

    # is a table by itself
    tagName: 'table'

    # it receives the collection of elements
    initialize: (options) ->
        @collection = options.collection

    # and renders each row ...
    render: ->
        @collection.each(@renderRow, @)
        @
    # ... in a element table row view
    renderRow: (row) ->
        rowView = new App.View.ElementTableRow(model: row)
        @$el.append(rowView.render().el)

#  The element table row ...
class App.View.ElementTableRow extends Backbone.View
    # ... is itself a row
    tagName: 'tr'

    # and takes an element model
    initialize: (options) ->
        @model = options.model

    # it handles the click event ...
    events: {
        'click button': 'click'
    }

    # ... with full access to the model and the collection, which is a member
    # of the element model
    click: (evt) ->
        console.log(evt.target.name, @model, @model.collection)
        @$('td').toggleClass('red')

    # render uses the precompiled handlebars template to render the row,
    # no HTML in the view or the model necessary

    render: () ->
        @$el.html(rowTemplate(this.model.toJSON()))
        # Here I show/hide the buttons based on the element models data.
        # It would definitely be better to not render the buttons in first place
        if not @model.get('haveDataBytes')
            @$('button').hide()
        @


# simple start script
$(() ->
    # 'load' the data as a collection
    collection = new App.Collection.Elements(data)

    # check the elements
    console.log(collection.models)

    # create and render the table view
    view = new App.View.ElementsTable(collection: collection)
    $('.table').append(view.render().el)
)

И последнее, но не менее важное: doFunction должно жить в представлении (см. click в App.View.ElementTableRow) или вызываться обработчиком щелчка App.View.ElementTableRow.

...