Opened 6 years ago

Closed 6 years ago

Last modified 6 years ago

#10623 closed feature (wontfix)

A way to access original options object on widget's creation

Reported by: sparkybg Owned by: sparkybg
Priority: minor Milestone: none
Component: ui.widget Version: 1.11.1
Keywords: Cc:
Blocked by: Blocking:

Description

As stated in documentation, the widget options, provided when widget is instantiated, is deep copied and "extended" with default options and options, provided from _getCreateOptions. But sometimes, a widget may need some of the properties in the original options as an object, not a deep copy.

For example, imagine a group of data widgets (inputs for example), storing their values in different properties of common plain object. For the moment this common data storage object cannot be provided in widgets creation options. The only way is to use $(someting).widget("option",{"dataStore": commonObject}) after the widget is already created.

There is workaround for this, overloading the _createWidget method but this method is not mentioned in API documentation at all, so I consider this as unacceptable.

One way it can be implemented is passing the options object to the _create method, or storing it somewhere, for example in "_options" variable in widget's instance. Both ways will preserve compatibility with current implementation of $.widget.

Change History (7)

comment:1 Changed 6 years ago by Scott González

Owner: set to sparkybg
Status: newpending

Why are you setting a default value for the data store? You'll need to provide realistic use cases for us to even consider this.

comment:2 Changed 6 years ago by sparkybg

Status: pendingnew

Ok, I will try to be as specific as I can.

Here is a hypothetic case:

  1. We have a "commonDataStore" object:

    var commonDataStore={name: "Steven", age:15, location: "USA"}

  1. We have 3 "myInput" widgets bound to this data store object, created as follows:
        $("#nameInput").myInput({field:"name", dataStore:commonDataStore});    
        $("#ageInput").myInput({field:"age", dataStore:commonDataStore});
        $("#locationInput").myInput({field:"location", dataStore:commonDataStore});
    
  2. The widgets purpose is to save their value to the common data store object for further processing, either by a web application itself, or to send the entire object to the server via AJAX request or whatever. The widgets themselves are doing this for example every time they loose focus. In order to do so, the widgets must know what common object they are using, and I think the most obvious way to do this is to provide this common data store object when they are created. But, with current implementation of widget factory, when "_create" method is invoked, all pure objects in "this.options" are already deep copied, and extended with default options if available. So, the widgets receive a copy or the "commonDataStore" object instead of the object itself. And, I cannot find any "legal" way to get access to the original data store object other than providing it explicitly after the widgets are created:
       $("#nameInput").myInput("option","dataStore",commonDataStore);
       ....
    

So, I think it will be a nice feature if at least the widget's "_create" method has access to the options as provided on creation, not only the copied and extended version of them. For the moment, only the internal "_createWidget" method has access to them. In fact this method itself is making the copy of the options and extends them with defaults.

This overload works and solves the problem, but _createWidget is internal non-documented function, and I think it is not a good practice to use it:

        _createWidget: function(options){
            this._options = options; //alt: this.dataStore=options.dataStore;
            this._superApply(arguments);
        },

Last edited 6 years ago by sparkybg (previous) (diff)

comment:3 Changed 6 years ago by Scott González

Resolution: wontfix
Status: newclosed

Just make your data store use a real constructor and you won't have a problem. Only plain objects are extended.

comment:4 in reply to:  3 Changed 6 years ago by sparkybg

Replying to scott.gonzalez:

Just make your data store use a real constructor and you won't have a problem. Only plain objects are extended.

For several reasons, I cannot. The data store object in my case is a part of array of plain objects, and the array is a result of AJAX response which the browser itself already parsed. Changing records in the array to use constructors may be a performance penalty - there may be thousands of records in the array.

Anyway it was just a proposition. I think it would be a good practice to give a way for widget instance to decide how to extend it's options out of the default behavior.

P.S.: Another possible way to do this is to make _createWidget function to use "this._extendOptions" instead of "$.widget.extend", This way, it will be possible to overload the default behavior in widget's definition. Another possible way is to make "_createWidget" to call "this._extendOptions", defined in Widget prototype, which then, if overloaded, will be able to decide if and when to use "$.widget.extend".

As far as I can see, up to version 1.8, the options are copied with "$.extend(true,...)" instead which creates copies of Arrays also. Then, in 1.9 and up to 1.11 it uses "$.widget.extend" which does not copy Arrays. This creates incompatibility issues. All this can be avoided in future versions just by providing a documented way for a widget to decide what to do with it's options on creation.

Last edited 6 years ago by sparkybg (previous) (diff)

comment:5 Changed 6 years ago by Scott González

So provide the array, that also won't get clobbered. There are already two ways to handle this, we're not going to add a third.

comment:6 in reply to:  5 ; Changed 6 years ago by sparkybg

Replying to scott.gonzalez:

So provide the array, that also won't get clobbered. There are already two ways to handle this, we're not going to add a third.

Forget about the exact case I provided. My proposal was not to create a third or fourth way to do something, but to think about how/if it is possible to overcome this restriction once and for all for any case in any future versions of the widget factory.

comment:7 in reply to:  6 Changed 6 years ago by Scott González

Replying to sparkybg:

Forget about the exact case I provided.

Sorry, without specific use cases, nothing ever gets added.

Note: See TracTickets for help on using tickets.