How do I use X-editable on dynamic fields in a Meteor template now with Blaze?

前端 未结 6 2094
忘了有多久
忘了有多久 2021-01-01 05:42

I had x-editable working in Meteor 0.7.2 but since upgrading to 0.8.0 it no longer renders correctly. I tend to end up with a bunch of Empty tags. This is frustrating becaus

6条回答
  •  甜味超标
    2021-01-01 06:04

    EDIT: Much easier to implement now in Meteor 0.8.3:

    Template:

    
    

    Code:

    Template.docTitle.rendered = ->
      tmplInst = this
    
      this.autorun ->
        # Trigger this whenever data source changes
        Blaze.getCurrentData()
    
        # Destroy old editable if it exists
        tmplInst.$(".editable").editable("destroy").editable
          display: ->
          success: (response, newValue) -> # do stuff
    

    For this to be most efficient, make sure the data context of the editable template is only the field being edited, as in the example above with {{> docTitle someHelper}}.


    Outdated information follows for Meteor 0.8.0 to 0.8.2

    I also had to do this but wasn't sure about using the global helper in my app. So I tried to accomplish it by just changing the behavior of the editable.

    The main things that needed to be done, after perusing the docs and source, were:

    • Set the value of the form from the field text
    • Override the display function so that reactivity of text updated by Meteor doesn't break
    • Make sure the above two functions don't break

    Here's the code (apologies for Coffeescript):

    Template.foo.rendered = ->
      container = @$('div.editable')
      settings =
        # When opening the popover, get the value from text
        value: -> $.trim container.text()
        # Don't set innerText ourselves, let Meteor update to preserve reactivity
        display: ->
        success: (response, newValue) =>
          FooCollection.update @data._id,
            $set: { field: newValue }
          # Reconstruct the editable so it shows the correct form value next time
          container.editable('destroy').editable(settings)
      container.editable(settings)
    

    This is ugly because it destroys and re-creates the popover after setting a new value, so that the form field updates from the correct value.

    After some more reverse engineering, I found a cleaner way to do this that doesn't involve destroying the editable. Gadi was right on that container.data().editableContainer.formOptions.value has something to do with it. It's because this value is set after the update because x-editable thinks it can cache this now. Well, it can't, so we replace this with the original function so the value continues being updated from the text field.

    Template.tsAdminBatchEditDesc.rendered = ->
      container = @$('div.editable')
      grabValue = -> $.trim container.text() # Always get reactively updated value
      container.editable
        value: grabValue
        display: -> # Never set text; have Meteor update to preserve reactivity
        success: (response, newValue) =>
          Batches.update @data._id,
            $set: { desc: newValue }
          # Thinks it knows the value, but it actually doesn't - grab a fresh value each time
          Meteor.defer -> container.data('editableContainer').formOptions.value = grabValue
    

    Notes:

    • $.trim above was taken from the default behavior to render value
    • For more discussion about this see https://github.com/nate-strauser/meteor-x-editable-bootstrap/issues/15
    • This is all an ugly hack, hopefully in the future we'll see better support for two-way variable bindings in Meteor.

    I will try to make this more concise in the future pending better support from Meteor for depending on data reactively.

提交回复
热议问题