Opened 6 years ago

Closed 3 years ago

#17162 closed defect (patchwelcome)

dojox/mvc/sync formatter is not run for initial copy

Reported by: ben hockey Owned by: Ed Chatelain
Priority: undecided Milestone: 1.11
Component: DojoX MVC Version: 1.9.0
Keywords: Cc: Akira Sudoh
Blocked By: Blocking:

Description

in the code below, i'm trying to bind the title of a widget to the title of a selected item. for simplicity, selected is more or less just an empty instance of dojo/Stateful when it's created and then as a user selects an item from a list, the properties of that item are set on selected - something like selected.set(item);.

sync(selected, 'title', widget, 'title', {
        bindDirection: sync.from,
        converter: {
                format: function (title) {
                        return title || 'New Item';
                }
        }
})

i have a formatter to display 'New Item' whenever the currently selected item has no title - this is the case when at first nothing is selected - but the first binding doesn't cause the formatter to be called because the internal copy function used by sync is passed undef as the old value.

for this initial copy, my widget's title doesn't match the formatted value that i expect when the model's title is undefined because the logic to do the copying sees that the model's title is undefined which is equal to the old value passed to copy so the formatter is never called.

i created http://jsfiddle.net/neonstalwart/5KysC/ to demonstrate

Change History (4)

comment:1 Changed 6 years ago by Ed Chatelain

Cc: Akira Sudoh added

Asudoh, what are your thoughts on this? I guess he could provide a custom equals function on the sync to handle this himself if we can not come up with a generalized solution which we do not think will break other applications.

comment:2 Changed 6 years ago by ben hockey

i looked at a custom equals function but i'm not sure it will work. it is passed undefined and undefined and normally i would want undefined and undefined to be equal so i would need some more context passed to the function to treat this as a special case. since the sync function has all the context necessary to apply this logic that's where i was thinking it might happen. the logic i'm looking for in my case is that for the initial sync if !equals(format(source[prop]), target[prop]) then a copy is needed - or maybe just always do a copy for the first sync if there is a formatter (maybe some other similar alternative).

comment:3 Changed 6 years ago by Akira Sudoh

The code tracks change in value of source, in order to prevent redundant copy. Data binding converter is for supporting model and widget have different format, for example, Date objected in model and formatted date in widget. Given the current underlying design: In order for widget to show a default value, I guess it'd be more natural doing that in widget, instead of in data binding converter.

I see the desire for injecting a function there to just work, though. It'd be a good thing to consider in future design of data binding. Meanwhile, I think below code would work as a workaround:

var format = function(title){
    return title || 'New Item';
};

sync(selected, 'title', widget, 'title', {
    bindDirection: sync.from,
    converter: {
        format: format
    },
    equals: function(old, current){
        if(old === void 0 && current === void 0 && format(current) !== void 0){
            return false;
        }
        return sync.equals(old, current)
    }
});

comment:4 Changed 3 years ago by dylan

Milestone: tbd1.11
Resolution: patchwelcome
Status: newclosed

dojox/mvc is not actively maintained. If someone wants to work on pull requests for the issues, we'll consider them.

Note: See TracTickets for help on using tickets.