Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Persisting Edits #26

Open
maxwellmstein opened this issue Aug 21, 2017 · 5 comments
Open

Persisting Edits #26

maxwellmstein opened this issue Aug 21, 2017 · 5 comments

Comments

@maxwellmstein
Copy link

I suppose this is a flavor of an Enhancement Request, but I'm curious if you had thoughts around how a "Save" button would work here. My first thought is to loop through the rowDatas and look for dirty, but the way it's stored key'd by columnName, it seems like a lot of effort to loop through every column name on every row to check for a dirty flag. I haven't done any performance tests with that yet, so it's entirely possible that it's not a factor; even at large data volumes, but my instinct is that it would be slow.

I'm going to try a few things along that route, but I thought I'd float this for discussion.

Another thought involves using some sort of dataProviderComponent that is wired into each cell (row maybe?), and has direct access to shared dataStore (via the window? --- similar to your redux store component setup). I suppose it would also be possible to leave the store at the table level and communicate changes by events, but my experience in the framework gives me a bad feeling about that. (Speed wise, and falling into the nightmare of keeping attributes/data in sync between multiple components.)

@maxwellmstein
Copy link
Author

with 10000 rows i'm seeing 3-5ms on chrome....so maybe this is a moot point:

whosDirty : function(cmp){
        console.time('test');
        cmp.find('tableBody').get("v.body").forEach(function(item){
            _.each(item.get('v.rowData'), function(rd, key){
                if(rd.isDirty){
                    console.log("I'm dirty:" + key);
                }
                
            });
        });
        console.timeEnd('test');
    }

(about the tablebody.find stuff....I'm constructing the rows dynamically without an iteration, so a straight cmp.get('v.data') is giving me a different object than what ends up being on the row...ugh)

@madmax983
Copy link
Owner

I have been giving saving a lot of thought, but I've been heads down on the searching, filtering and sorting when I've had free time for this.

At the very least, I think the grid should be providing something like whosDirty in an invocable manner so we don't need to re-implement it on every new grid.

@madmax983
Copy link
Owner

Also, how is constructing the rows dynamically going for you? I experimented with that for a bit, and still think it could buy performance savings when the view is updated, especially if some caching mechanism is added for rows that already been seen before. A lot more code overhead to keep track of the bits and bobs though.

@maxwellmstein
Copy link
Author

maxwellmstein commented Aug 21, 2017

I tried a few things, the ultimate goal being when you get close to the bottom scroll wise, it loads the next 'page' of records. I've tried 5 implementations of helper.addRows for this, adding 50 rows to the bottom each time:

(ps - my c:row body for this was just a hardcoded TR, no dynamic cells)

  1. looping over next 50 data items and producing an array of configs to pass to A.createComponents
  2. looking over the next 50 items calling A.createComponent inside the loop
  3. raw HTML fragment.appendChild
  4. Using aura:iteration and just increasing the items is v.items
  5. Using a 'component store' so I call createComponents doing init, and create say 1000 components, then, in the addRows method, I can pull from the 'store' and append to the tableBody.v.body

In the chrome performance tab you can clearly see the bottle neck is the THOUSANDS of function calls in the createComponent spiderweb. My not scientific benchmarks were approx:

  1. 1300ms
  2. 3000ms
  3. <400ms
  4. 2000ms
  5. 700ms (WAY longer on init)

Method 5 is very intriguing, if you could find a way to fill the store during user interaction lulls, a few pieces at a time. Or do something with WebWorkers. Still, HTML Tables? this is web 101.

I've spent a good amount of time in the source for ui:virtualDataGrid in the aura framework and force:inlineEditGrid, but they take advantage of APIs that are blocked with locker service. I keep wondering if just doing something on top of lighting, like baking in slickgrid or equivalent would be better than this hassle. That or just deal with less than ideal performance and see what the next 6 months brings.

I'm not actually using your source for this, or I'd send you a branch. I had developed something pretty similar on my own when I found this, and thought maybe we could synergize a bit. That said, I do have the code in a DX repo, so if you're interested, I can share.

@madmax983
Copy link
Owner

Yeah, I think doing something with slickgrid is probably the path of least resistance right now. But my original goal with this was to make it as natively lightning as possible to force myself to use the framework. That and lightning:treegrid still being Spring '18 at the earliest were the motivations for this project.

Thank you for sharing!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants