Giter Site home page Giter Site logo

Deep setting/getting/observing about svelte HOT 10 CLOSED

sveltejs avatar sveltejs commented on September 27, 2024 2
Deep setting/getting/observing

from svelte.

Comments (10)

evs-chris avatar evs-chris commented on September 27, 2024

It took me a little while to find the viewmodel 😄, and as it stands, it's refreshingly simple. Perhaps there could be an option to plug in viewmodels that implement a prescribed API - kinda like ractive adaptors flipped on their heads? That would let some purpose-built library take over the whacky hijinks involved with component.set('foo', { bar: { baz: 123 } }) triggering a foo.bar.baz observer.

from svelte.

Rich-Harris avatar Rich-Harris commented on September 27, 2024

kinda like ractive adaptors flipped on their heads

I think we're thinking on similar lines! Perhaps something like

import FirebaseAdaptor from 'svelte-firebase';
const adaptor = new FirebaseAdaptor( someComponent, firebaseRef );

adaptor.set( 'x', y );
adaptor.observe( 'some.deep.keypath', callback );

Big related unsolved question is whether there's a good way to only trigger needed updates in response to a deep set – right now it updates the entire component, and sort of gets away with it because there's not much overhead in the system, but it's not totally ideal. Is most important with lists – in my initial sketches I wondered about exposing add and remove methods that could take advantage of internal logic...

component.myList = {
  add ( index, items ) {
    // insert new iterations, don't update existing ones
  },

  remove ( index, count ) {
    // remove iterations
  }
}

...the thinking being that you could build an adaptor-like interface around it similar to ractive.merge(...) or ractive.push(...) etc, without needing to include those methods with each component.

from svelte.

evs-chris avatar evs-chris commented on September 27, 2024

Was looking into #51, and I think some sort of shared viewmodel-ish thing may become necessary as more complex cases pop up. The nested partials case kinda needs something to handle the nested keypath/data scenario, and if you address that by making partials private pseudo-components, you still have may have issues with SSOT and sibling things pointed at the same data getting out of sync. I don't have a wizard hat though, so I may be a bit off base 😄

from svelte.

mefjuu avatar mefjuu commented on September 27, 2024

Any chances for seeing it before 2017? :) Great job with Svelte, but lack of set('so.so.deep.key', val) (especially in templates) hurts...

How do you handle such updates in a current version?

from svelte.

Rich-Harris avatar Rich-Harris commented on September 27, 2024

@mefjuu currently you would have to do it in two steps, like so:

var so = component.get( 'so' );
so.so.deep.key = 'other';
component.set({ so });

Am hesistant to add it to the core API, but it's something that could be done via a wrapper:

function wrap ( component ) {
  return {
    get ( keypath ) {
      const keys = keypath.split( '.' );
      let value = component.get( keys.shift() );
      while ( keys.length ) value = value[ keys.shift() ];
      return value;
    },

    set ( keypath, value ) {
      const keys = keypath.split( '.' );
      const lastKey = keys.pop();
      const object = this.get( keys.join( '.' ) );
      object[ lastKey ] = value;

      const data = {};
      data[ keys[0] ] = component.get( keys[0] );
      component.set( data )
    }
  };
}

const wrapper = wrap( component );
wrapper.set( 'so.so.deep.key', val );

from svelte.

Rich-Harris avatar Rich-Harris commented on September 27, 2024

Going to close this issue as I don't think it's necessary to have this in core — could certainly be put into an external wrapper if there's popular demand

from svelte.

aubergene avatar aubergene commented on September 27, 2024

Is there a good pattern for deep observing?

from svelte.

Rich-Harris avatar Rich-Harris commented on September 27, 2024

@aubergene I'd probably create a new method for that. Something like this should work:

export default {
  methods: {
    observeDeep (keypath, callback, opts) {
      const parts = keypath.replace(/\[(\d+)\]/g, '.$1').split('.');
      let last = undefined;
      return this.observe(parts.shift(), newValue => {
        for (let i = 0; i < parts.length; i += 1) newValue = newValue[parts[i]];
        if (newValue !== last || typeof newValue === 'object' || typeof newValue === 'function') {
          callback.call(this, newValue, last);
        }
        last = newValue;
      }, opts);
    }
  }
};

We could add that to svelte-extras.

from svelte.

Rich-Harris avatar Rich-Harris commented on September 27, 2024

Update: observeDeep has been added to svelte-extras, in response to a StackOverflow question

from svelte.

jslegers avatar jslegers commented on September 27, 2024

Suppose I have a DataTable component, which uses a Table component, which uses a TableRow component, which uses a TableCell component, which uses a TableCellInput component.

Now, suppose I want to observe any changes in any TableCellInput of my DataTable at the DataTable level rather than at the TableCellInput. For example, suppose I want my DataTable to keep (1) track of user input, (2) trigger a valueChanged event at the DataTable level when a value changes, (3) trigger validation, (4) optionally send a PUT or PATCH request with all values in that particular TableRow to update the data in my dataStore on the server (if validation succeeds) and then (5) optionally reposition the TableRow in the Table if (the field that's been changed is a field that's being sorted on).

What would be the proper way to do that in Svelte?

Or to rephrase my question : how do I deal with observing changes to the properties of deeply nested components? Adding individual observers to every this.refs.table.refs.row[y].refs.cell[x].refs.input.value where x and y are respectively the column positions and row positions doesn't seem quite efficient to me. Also, I can't exacly say it looks very elegant!

I suppose a whole lot more elegant approach than a whole bunch of observers would by be to trigger an event in my TableCellInput component and have it bubble / propagate all the way to the DataTable component. That way, I could emit an event at the TableCellInput level whenever a value is changed and capture the event at the DataTable level. However, I don't think that's currently supported, right?

See also #576 (comment)

from svelte.

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.