So naive code like this...
removeBar: function() {
this.set('foo.bar', undefined);
}
With the intent unset a value on a property will actually have unfortunate side effects, if you have any computed methods, or things like dom-if that watch for a change on bar. Since we are setting bar back to undefined it kicks us back into the skip this eval mode for any watcher on bar, which can be quite problematic.
xref https://github.com/Polymer/polymer/issues/2447
Thoughts?
In BB world
If anyone stumbles across this, a hack workaround is to set the value to null instead of undefined
this.set('foo.bar', null);
I would rather suggest such workaround:
this.set('foo.bar', null);
this.set('foo.bar', undefined);
as then you will notify the things, and end up with this.foo.bar === undefined
Hello,
Is there any update on this - the ability to unset object keys seems quite essential for many cases when working with slightly more complex state objects.
Does this issue affect 2.x as well? Any plan to address this with the new data binding changes? @sorvell @kevinpschaaf?
this.set('foo.bar', null);
this.set('foo.bar', undefined);
is not equal to... delete foo.bar, one produces
{ bar: undefined }
while the other produces
{}
+1 for a way to do this.delete(path) ?
But both still produce the same on a weak compare ==?
Is the delete an issue related to garbage collection, memory and state? Or just one about consistency?
There are methods to delete certain types, Polymer had used weak map collections to maintain anonymous and unique session specific collections, but I believe that as v1 arrived they offered users a richer observe API, the ability to manipulate batched properties on command using a little creative function swapping binding. And then native took care of some of the delete functionality
How browsers implement some requirements regarding weak map garbage collection and type fealty may change things
But from my undetstanding. Native can delete any property including another object which is a property of a. Object , provided that object or property has not been hoisted to global scope
The good and the bad of this hoisting one could write volumes on from a security or adored utility perspective
But the issue was delete
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/delete
There are other. Clear etc operators for map etc
Sent from my iPhone
On Oct 3, 2016, at 10:49 AM, Quang Van [email protected] wrote:
this.set('foo.bar', null);
this.set('foo.bar', undefined);
is not equal to... delete foo.bar, one produces{ bar: undefined }
while the other produces{}
+1 for a way to do this.delete(path) ?—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub, or mute the thread.
This is creating me a real problem.
I have an iron-ajax element:
<iron-ajax id="aj" params="{{extraParams}}" url="/stores/usersList" handle-as="json" last-response="{{data}}" on-response="_loaded" ></iron-ajax>
I also have some paper-checkboxes which will call _flagToggled on-iron-change="_flagToggled".
<paper-checkbox noink checked="{{_isFlagChecked('admin',flags)}}" flag-name="admin" on-iron-change="_flagToggled">Admin</paper-checkbox>
<paper-checkbox noink checked="{{_isFlagChecked('hidden',flags)}}" flag-name="hidden" on-iron-change="_flagToggled">Hidden</paper-checkbox>
I want the checkboxes to change extraParams so that admin and hidden are either set to true or nothing.
This is what I have to do right now:
_flagToggled: function( e ){
var l = e.currentTarget;
var flag = l.getAttribute('flag-name');
var checked = e.currentTarget.checked;
if( checked ) this.set('extraParams.'+ flag, true );
else {
if( this.extraParams ){
delete this.extraParams[ flag ];
var ep = {};
for( var k in this.extraParams ){
ep[ k ] = this.extraParams[ k ];
}
this.set('extraParams', ep );
}
}
},
Basically, the only chance to actually set extraParam correctly is to create a full copy of it.
Note:
if( checked ) this.set('extraParams.'+ flag, false ); won't work as it will set a filter on the server where values need to be set to false, which is NOT what I wantif( checked ) this.set('extraParams.'+ flag, undefined ); won't work as it will send hidden=undefined to the serverdelete this.extraParams[ flag]; this.set('extraParams', extraParams); won't work because extraParams gets cached and notifications won't go outThis must be a common use-case. I am not sure how to "solve" it.
Okay, I took a stab at this issue and sadly it is a lot more complicated than I expected. The gist of the issue is that the data-binding has an universal assumption of eagerly setting a property. Since deletion (together with the semantics of field in object) is strictly different, you need to explicitly delete object[field]. This means that whenever we do an assignment to any store or element (which we do a lot) has to be abstracted to delete. This results in a lot of duplication throughout the data-binding system, for example require a new implementation of _setPendingPropertyOrPath and _setPendingProperty to deal with this.
Overall, while I would really like this feature to exist, deletion seems too intrusive in the current state. Since Polymer 2, you can do this.set('path.value', undefined) to get the correct data-binding updates. However, deletion of the field in the object (per the above comment) seems infeasible in the current state :cry:
@TimvdLippe I think lit-html or using something like redux might be best bet for the time being.
Per discussion: might just work if we can fix this use-case: http://jsbin.com/lemixor/1/edit?html,output e.g. delete this.prop.field and then this.notifyPath('prop.field', undefined). This is now not working probably because there is a conditional somewhere.
Opened #4999 for implementation discussion. So far I am quite pessimistic that we can change it, as there are lot of checks that prohibit the propagation of "nothing" :cry:
Closing this issue per https://github.com/Polymer/polymer/pull/4999#issuecomment-357517032 Sadly there we see no way for a performant and small solution to this problem. In Polymer 2, you can set to undefined and trigger all side-effects. The actual delete of a field is however not possible to propagate. Given the consequences of these design requirements, we have to close this :cry:
@TimvdLippe but it seems setting to and notifying undefined does not work either. https://jsbin.com/jicagumude/2/edit?html,console,output
Most helpful comment
is not equal to...
delete foo.bar, one produceswhile the other produces
+1 for a way to do
this.delete(path)?