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

Preserve custom HTML5 data attributes #239

Closed
ghost opened this issue Jan 3, 2014 · 61 comments
Closed

Preserve custom HTML5 data attributes #239

ghost opened this issue Jan 3, 2014 · 61 comments

Comments

@ghost
Copy link

ghost commented Jan 3, 2014

Feature request

Preserve custom HTML5 data attributes, so that in this case data-fruit won't disappear when going from <select> to Selectize:

http://jsfiddle.net/k44p2by6/

@MaherSaif
Copy link

+1

@MaherSaif
Copy link

I've created a plugin to override -not extend- the function which changes the original select options.

Selectize.define('preserve_original_select', function(options) {
  var self = this;

  this.updateOriginalInput = (function() {
    var original = self.updateOriginalInput;
    return function() {
      var i, n, options, self = this;

      if (self.$input[0].tagName.toLowerCase() === 'select') {
        for (i = 0, n = self.items.length; i < n; i++) {
          self.$input.find('[value="'+self.items[i]+'"]').prop('selected', true);
        }
      } else {
        self.$input.val(self.getValue());
      }

      if (self.isSetup) {
        self.trigger('change', self.$input.val());
      }

      // original.apply(this, arguments);
    };
  })();

});

Don't forget to load the plugin.

@xak2000
Copy link

xak2000 commented Mar 19, 2014

Plugin is good but data-attributes in OPTIONs shouldn't disappear by default.
It is hurt for transparent selectizing of existing SELECT elements.

@dylanbromby
Copy link

Yes! Selectize should be updated to allow for the preservation of custom attributes in each option.

@vizcay
Copy link

vizcay commented May 17, 2014

+1

@ryannealmes
Copy link

Would really appreciate a fix to this. Can't get plugin working.

@jcomack
Copy link

jcomack commented Aug 25, 2014

+1

@jontjs
Copy link

jontjs commented Aug 27, 2014

Agreed, selectize should retain data attributes

@nexenator
Copy link

+1

@dylanbromby
Copy link

I have no idea how I got CC'd on all the posts to this list, but I'd appreciate it if it stopped. Thanks!

On Sep 1, 2014, at 8:05 AM, Stephan Helbig notifications@github.com wrote:

+1


Reply to this email directly or view it on GitHub.

@arjan0307
Copy link

+1

3 similar comments
@jensljungblad
Copy link

+1

@telmogh
Copy link

telmogh commented Dec 17, 2014

+1

@iamroi
Copy link

iamroi commented Dec 21, 2014

+1

@iamroi
Copy link

iamroi commented Dec 21, 2014

This is working.

$(ele).selectize({
.....
dataAttr: 'data-extra', //default is data-data
.....
}
});

Add data-extra in every option as json encoded, Ex
option value="one" data-extra="{'test':'123'}"
option value="two" data-extra="{'test':'456'}"

Get the selectize instance using this, var selectize = $(ele)[0].selectize

Users selected options can be found here: selectize.items

Data attributes of all options can be found here: selectize.options

In our case it will be,
selectize.options['one'].test
selectize.options['two'].test

Let me know if this is working.

@indrimuska
Copy link

I think that it's already possibile to do that without extending the plugin (certainly, a full support will be appreciated) simply using the onInitialize method in combination with the revertSettings attribute (jsfiddle):

$('select').selectize({
    onInitialize: function () {
        var s = this;
        this.revertSettings.$children.each(function () {
            $.extend(s.options[this.value], $(this).data());
        });
    }
});

The possibilities are infinite with this feature, like a FULL HTML SELECT.

@JamesWilsonNovel
Copy link

@indrimuska You are a hero sir. That works like charm!

@indrimuska
Copy link

@JamesWilsonVSolvit 😄 thank you man!

@kimek
Copy link

kimek commented Apr 20, 2015

works like charm, but not for option groups as their are undefined :(. any idea how to get to next level.. ( get each from option group and keep custom-data ? )

@indrimuska
Copy link

Hi @kimek, as you can see, revertSettings has a $children attribute that contains all the previous children of the original select you define.
If your select has got many <optgroup>s, the $children attribute contains these jquery elements, not the <option>s you want. That's why you get undefined as value of those datas.

schermata 2015-04-20 alle 15 28 10

The simplest way to overcome this problem is to look for the <option>s inside the <optgroup>s as you normally do in jQuery (.find()).
Here it is an example.

@kimek
Copy link

kimek commented Apr 20, 2015

Thanks for fast replay and for help
The magic for me is how You looping children more than 'real optgroup' children.
children = this.revertSettings.$children; // its loop only for option group in my ex. is 6 optgroups

if (children.first().is('optgroup')) { // why this is not a loop ?
children = children.find('option');
}

Maybe this will help how i'm thinking, probably it's bad way..
var s = this;
x = s.options; // all items
$.each(x, function(i, val) {
$.extend(s.options[i.value], //here go data by jQ);
})
I really don't get it how you guys changing all '' here.
Thanks in advance

@indrimuska
Copy link

Hi @kimek.
In the fiddle I posted, the variable children initially assumes the value of the $children attribute offered by the plugin:

var s = this, children = this.revertSettings.$children;

Now, I don't know if children contains a collection of <option>s or a collection of <optgroup>s, so I have to catch the second situation in that way:

// if the first element of the collection is an `<optgroup>`
// I have to look through this list looking for the the `<options>`s.
if (children.first().is('optgroup')) {
    children = children.find('option');
}
// Now `children` is definitely a collection of `<option>`s.

In your case, you can remove the if-statement and use the corresponding block directly:

var s = this, children = this.revertSettings.$children.find('option');

@markudevelop
Copy link

@indrimuska your example is awesome I was looking for creating something like this and boom I found the perfect 1 to 1 example :) https://jsfiddle.net/8y9xkb0o/ I wanted to ask you if you know a way around the delay of the images loading? Any way to load them before opening the select? I'm trying to see the images instantly. Thanks a lot.

@indrimuska
Copy link

Hi @voidale, your problem is about to preload the image before the select has been opened. If you google it you can find many way to preload an image by using javascript or css. I think that the better solution for you is to parse the data-attributes as jquery element looking for src-attributes of the images, then to preload them like this:

var image =  new Image();
image.src = $(this).attr('src');

Here it is an example.

EDIT:
I just notice that the images are loaded every time the $(data.html) is called, so you don't even have to load the image manually. I tested this fiddle on Chrome and Firefox, I'm not sure about the behavior on the other browsers.

@markudevelop
Copy link

@indrimuska Hey, That's awesome I did google it and founds some solutions but didn't really like them all. This seems much more light weight. I wasn't aware of the Image api. It's really awesome thanks a lot for the information I also noticed that Image instance has onload function that can be really useful. Thanks again now this seems so easy I thought it will be really hard to fix :)

@MarcusHallettUAH
Copy link

I think this feature would be delightful.

@stephanvierkant
Copy link

+1

1 similar comment
@pixedelic
Copy link

+1

@joallard joallard changed the title Feature request: Preserve custom HTML5 data attributes Preserve custom HTML5 data attributes Jul 20, 2016
@ghost
Copy link
Author

ghost commented Jul 21, 2016

Hi,

I believe custom attributes should be transferred to both the Selectize dropdown and its input items.

In our case, we wanted multiple attributes like data-category, data-subcategory, data-article-type etc. Right now, only the original children's value are transferred as data-value, so we had to come up with a workaround where we placed multiple attributes inside each value like value="foo|bar|baz".

Hope that helps!

OP

@joallard joallard added this to the 0.13.0 milestone Jul 21, 2016
@oranges13
Copy link

The comments and workarounds in this thread so far are great, but what still isn't happening is the <option> element is not having the data attributes applied to it. The full HTML example above works well for displaying content from attributes, but the original option loses them.

In my use case, I'm using the data to populate subsequent things, and losing the attributes means this doesn't work.

Something like $("#my_select_box").find(':selected').data("color") no longer works because the <option> is stripped of the attributes.

@xak2000
Copy link

xak2000 commented Jul 21, 2016

My use case was absolutely the same. When you already have existing select on the page and it has some JS logic on it, this logic stops work when you "selectize" this select. If the attributes were not cut, then selectizing operation would be completely transparent to underlying JS code, which works with vanilla select element.

Why I want my JS code to work with vanilla select instead of produced selectized component? Because it is convinient. I can unselectize my select element any moment later and nothing stops to work. Also it cound be backward compatability: in legacy project I don't want to change any JS code just for selectizing my select elements.

@espen
Copy link

espen commented Jul 26, 2016

@joallard OP has an example at http://jsfiddle.net/k44p2by6/. I'm thinking the same as OP here. Have data-attributes in the select option elements copied over to the Selectize items.

This raises a few questions regarding for example entering input values from JavaScript instead of HTML. And also how Selectize store this data internally. Now it has to store attributes in addition to key/value. And should it be possible to define data-attributes using JS or just limit it to HTML input creation?

@oranges13
Copy link

oranges13 commented Jul 26, 2016

I successfully managed to modify the code locally to work when you load in
the options via AJAX, however it doesn't translate when the options are
loaded from HTML.

I gotta work on it some more but hopefully will have some idea of changes
that could be included in a PR soon.

On Tue, Jul 26, 2016 at 11:00 AM, Espen Antonsen notifications@github.com
wrote:

@joallard https://github.com/joallard OP has an example at
http://jsfiddle.net/k44p2by6/. I'm thinking the same as OP here. Have
data-attributes in the select option elements copied over to the Selectize
items.

This results in some questions regarding for example entering input values
from JavaScript instead of HTML. And also how Selectize store this data
internally. Now it has to store attributes in addition to key/value. And
should it be possible to define data-attributes using JS or just limit it
to HTML input creation?


You are receiving this because you commented.
Reply to this email directly, view it on GitHub
#239 (comment),
or mute the thread
https://github.com/notifications/unsubscribe-auth/AAuFpiaYOLXMI_1DBFJp4kDun_nQc18Xks5qZiETgaJpZM4BXMdG
.

@cyphix333
Copy link

+1

@samstickland
Copy link

Here's my use case.

I would like to be able to pass data attributes from the original options, onto the selectize options, so that I can later check them in a change event.

For example, my selectize list might be a list of countries, some of which required a postcode if selected. Each option has data-postcode=true or data-postcode=false. The event handler would be able to see the data-postcode value for the selected option and then show or hide the postcode field.

@WouterSchoofs
Copy link

+1

@ghost
Copy link
Author

ghost commented Jun 16, 2017

For me, the solution provided by @indrimuska preserve the data-attributes on select, but not for options.

@smohadjer
Copy link

smohadjer commented Dec 19, 2017

This is how I added a data-type="list" to my select options. The answer is based on stackoverflow post at: https://stackoverflow.com/questions/36512536/add-data-attribute-to-selectize-js-options

Markup:
<option data-data='{"type": "list"}' value="lorem">Lorem</option>

JavaScript:

$(#mySelect).selectize({
	render: {
		option: function (data, escape) {
			return '<div data-type="' + data.type + '">' + data.text + '</div>';
		}
	}
})

$(#mySelect).on('change', function(event) {
	var selectedValue = $(this).val();
	var $selectedOption = $(this)[0].selectize.getOption(selectedValue);
	if ($selectedOption.data('type') === 'list') {
		// do something
	}
});

@oranges13
Copy link

The solution presented by @smohadjer works for me:

<select class='form-control' id="productSelection">
	<option disabled="disabled" value="" selected>Please select a Product.</option>
	<option value="1234" data-data='{"name":"Product 1234"}'>Product 1234</option>
	....
</select>
$("#productSelection").selectize({
	render: {
		option: function (data, escape) {
			return '<div data-name="' + data.name + '">' + data.name + '</div>';
		}
	}
});

// To retrieve value
var selectedValue = $("#productSelection").val();
var name = $("#productSelection")[0].selectize.getOption(selectedValue).data('name');

@WadeTheFade
Copy link

But I'm not using markup, but loading in options from JS.

@oranges13
Copy link

@WadeTheFade In the case of data from JS this issue does not apply.

You can use the render function to add data attributes to the returned options and then query them when selected. This issue exists only if going from markup to selectize and wishing to retain data- attributes which existed on the original elements.

@Kazuto
Copy link

Kazuto commented Sep 3, 2018

I still can't get it to work. I've tried everything said here but my option field never receives any data values.

@smohadjer
Copy link

smohadjer commented Sep 8, 2018

@KazutoDE Here is a working example using solution I suggested earlier. Note that the data attribute (in this case data-continent) would be gone from original option element after selectize is initialized, but it will be preserved on markup generated by selectize, so you can still access it.

http://sandbox.saeidmohadjer.com/selectize/

@RudeySH
Copy link

RudeySH commented Dec 15, 2018

#1058 by @dakuzen highlights an important issue when using the $.extend workaround by @indrimuska.

@naveed-ahmad
Copy link

@KazutoDE @WadeTheFade

Sample code which worked for me.

HTML markup

<select>
<option data="{value:1, name: 'data 1'}" value="3"> First option</option>
<option data="{value:2, name: 'data 2'}" value="3"> Second option</option>
</select>

Init the selectize:

    $("select").selectize({dataAttr: 'data'})

Then you can fetch the data attributes using:

$("select").data().selectize.options['1'].name  => data 1
$("select").data().selectize.options['2'].name  => data 2

No need to overrider the selectize's renderer or anything.

@Younnah
Copy link

Younnah commented Feb 21, 2019

Hi @naveed-ahmad !
I tried your code, but it does not work at all for me...

When I write
$("select").data().selectize.options['1'].name
The result is "undefined"

To hope to have an exit, I have to write
$("select").data().selectize.options["3"]
and the result is
{text: "First", value: "3", $order: 1}

I have only this option in my options array...
I tested many things but nothing that works to recover the data...

Thanks for your help !

@naveed-ahmad
Copy link

@Younnah please see data attribute in my html, data="{value:1, name: 'data 1'}" i've name and value keys.

In your case keys are text, value, $order
so $("select").data().selectize.options['1'].name SHOULD be undefined.

Try $("select").data().selectize.options['1'].text and value should be First

@Younnah
Copy link

Younnah commented Feb 22, 2019

Yes, I see, but I can not access the attribute "name" in the "data" ...

@olucasu
Copy link

olucasu commented Jun 14, 2019

The way that worked for me

My only goal was to get the "selected" data-attr from the select

Get all data-attr
thanks to @indrimuska

$('.js-select').selectize({
        onInitialize: function () {
            var s = this;
            s.revertSettings.$children.each(function () {
                $.extend(s.options[this.value], $(this).data());
            });
        }
    });

then inside the eventListener:

$('.js-select').change((e) => { 
    const value = $(e.currentTarget).val(); 
    const options = $(e.currentTarget).data().selectize.options;
   // There you have it
   return options[value];
})


oyejorge added a commit to orchidjs/tom-select that referenced this issue Sep 18, 2020
@risadams
Copy link
Contributor

risadams commented Dec 1, 2020

closing stale issues older than one year.
If this issue was closed in error please message the maintainers.
All issues must include a proper title, description, and examples.

@risadams risadams closed this as completed Dec 1, 2020
@smohadjer
Copy link

@risadams I would have liked to see this shortcoming of Selectize to be fixed properly.

@databyte
Copy link
Collaborator

databyte commented Dec 1, 2020

It's a fair request. We're currently focused on getting the project actively maintained with security patches, dependency updates, processing the 120 opened PRs, etc.

This is a very valid enhancement and PRs are welcomed.

If anyone has bandwidth to work on this, open up a new PR against this issue and we can re-open it.

@databyte
Copy link
Collaborator

databyte commented Dec 1, 2020

Looks like maybe #1194 addresses this too. We need to process all the PRs including their functionality, test coverage and all the usual suspects including performance. If you want to pull that PR down and check it too, the more the merrier!

@danieleklekoo
Copy link

selectize.txt
In attachment my implementation.
In order to see the changes search for the word "attributes".

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