Coder Social home page Coder Social logo

Comments (11)

hagen avatar hagen commented on May 18, 2024

So it's because I'm binding child elements to nested properties. If you do this, changes to those properties in the child component don't come back up the chain. Is that correct?

from slim.js.

eavichay avatar eavichay commented on May 18, 2024

Question: Why do you place your own tag into the template? This is like having a recursive element which nests itself endlessly.

Does this works for you?

@tag('parent-component')
@template(`
  <child-component bind:items="parentProp.path.items"></child-component>
export default class ParentComp extends Slim {
  parentProp = {}
}

from slim.js.

eavichay avatar eavichay commented on May 18, 2024

Regarding bindings. If you make modifications into nested properties, there is no autodetection. Working with immutables is the practice.

If you have to work with nested changes, call the ::this.commit(propName) which will trigger as if it detected the change.

from slim.js.

hagen avatar hagen commented on May 18, 2024

The parent tag shouldn't be there. Bad, bad example! Sorry to confuse the issue.

Re bindings, this is the PAP approach right? If you have to bind to nested props, then use another (child) Slim component. Each level of nesting in my model should have a corresponding child Slim component that'll bind at that level. I think I've got it now.

from slim.js.

hagen avatar hagen commented on May 18, 2024

I can't get my head around this.
I have this structure:

@tag('parent-component')
@template(`
<div>
  <child-component bind:items="data.items"></child-component>
</div>
`
export default class ParentComp extends Slim {
  data = {}
}

And to this parent component, I inject the data model at 'create'. This model has a collection, items.

let data = {
  "items": [
    { "label": "First", "editing": false },
    { "label": "Second", "editing": false }
  ]
}

Injected:

Slim.plugin('create', element => {
  if (element.localName === 'parent-component') {
    element.data = data
  }
})

Now the child component

@tag('child-component')
@template(`
  <div>
    <h3>Title</h3>    
    <table>
      <tbody>
        <tr>
          <th>Header</th>
        </tr>
        <tr s:repeat="items as item">
          <th>
            <editable-link bind:label="item.label" bind:editing="item.editing"></editable-link>
          </th>
        </tr>
      </tbody>
    </table>
  </div>
`)
export default class ChildComponent extends Slim {
  items = []
}

And finally, the editable-link component (this is just an anchor/input toggle to allow editing of the anchor by clicking it. I'm using key.enter and key.escape as directives (thanks for that excellent example!)

@tag('editable-link')
@template(`
  <input s:if="editing" key.enter="onEnterPress" key.escape="onEscapePress" type="text" class="input" bind:value="label" autofocus>
  <a s:if="!editing" click="onLinkClick" bind>{{label}}</a>
`)
export default class EditableLink extends Slim {
  label
  editing
  onLinkClick() {
    this.editing = true
  }
  onEnterPress(target) {
    this.editing = false
    this.label = target.value
    // Trigger binding change?
    this.commit('label')
  }
}

What I'm expecting is that any changes down in editable-link to the item labels will be reflected back up in the data model injected into parent-component. Is this an accurate understanding? If not, how would I get the changed label values from editable-link back up into the data model?

from slim.js.

hagen avatar hagen commented on May 18, 2024

For now, I've worked around my lack of understanding using this.callAttribute() to pass data back up to parent elements. This eventually reaches the parent-component, where I replace the entire data property.

from slim.js.

eavichay avatar eavichay commented on May 18, 2024

So I understand everything works as expected now?

from slim.js.

hagen avatar hagen commented on May 18, 2024

Not as expected, but I've got it working with what I think is a work-around. I'm just seeking clarification as to how I correctly approach implementation of my scenario in Slim?

from slim.js.

eavichay avatar eavichay commented on May 18, 2024

The binding works locally on each component (repeated in your case). You should propagate it up either by event or by using callAttribute which is just a callback in an attribute... :)

I think that binding that component::label into the input::value may be incorrect in your case, try using the <input type="text" ... input="handleInput" ... /> which will trigger you function on every change in the text-input. This way you can capture the value as the user types. Capturing the label from the input and passing it back to the input seems like a no-op.

Makes sense?

from slim.js.

hagen avatar hagen commented on May 18, 2024

Yep, thanks. The callAttribute is super useful then, as it's almost the way to propagate up. I know you're doing more work on the doco - this seems a good one to include. I picked it up from looking through slim-docs repo.
Closing.

from slim.js.

eavichay avatar eavichay commented on May 18, 2024

The best practice in web components is to dispatch events. In case of custom elements, probably using shadow-dom, you should dispatch a custom event with an init object with composed = true.

this.dispatchEvent(new CustomEvent('myaction', { bubbles: true, composed: true, detail: whatever });

from slim.js.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.