17

I have this input with data-options attribute.

<input class="data" type="text" data-options="{maxDate:'0'}" />

I would like to load the datepicker using the data-options value as options. Now with the following code, doesn't work

$("input.data").each(function(){
    var dateOptions=$(this).data('options');
    $(this).datepicker(dateOptions)
});

but if I put the option on the js like in the following code, it works:

$("input.data").each(function(){
    $(this).datepicker({maxDate:'0'})
});

https://jsfiddle.net/VixedS/exfLf6o9/

If is somebody can, I would prefer an answer without eval.

Vixed
  • 3,429
  • 5
  • 37
  • 68

6 Answers6

11

When you call data function, it returns string so you have to convert it to an object and then pass it to datepicker and remove curly bracket from value of data-options.

Solutions:

1- Use eval

Javascript

eval('({' + $(this).data('options') + '})')

HTML

data-options="maxDate:'0'"

2- Jquery .data and surround your data attribute value by '

Javascript

$(this).data('options')

HTML

data-options='{"maxDate":0}'

3- use plugin or write custom function(the below code is written by @allenhwkim).

Javascript

function JSONize(str) {
  return str
    // wrap keys without quote with valid double quote
    .replace(/([\$\w]+)\s*:/g, function(_, $1){return '"'+$1+'":'})    
    // replacing single quote wrapped ones to double quote 
    .replace(/'([^']+)'/g, function(_, $1){return '"'+$1+'"'})         
}

jQuery.parseJSON(JSONize($(this).data('options')));

HTML

data-options="{maxDate:'0'}"

Note: all above solutions are tested and they works.

$("input.dataWithoutOptions").each(function() {
  $(this).datepicker({
    maxDate: '0'
  })
});

$("input.data").each(function() {
  var dateOptions = eval('({' + $(this).data('options') + '})');

  console.log(typeof($(this).data('options'))); //String

  console.log(typeof(dateOptions)); //Object


  $(this).datepicker(dateOptions)
});
input {
  display: block;
  margin: 10px 0 20px;
  padding: 5px;
}
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/themes/smoothness/jquery-ui.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.11.3/jquery-ui.min.js"></script>


This has options attr:
<input class="data" type="text" data-options="maxDate:'0'" />This is just a date pick:
<input class="dataWithoutOptions" type="text" />

Jsfiddle

Community
  • 1
  • 1
Alex
  • 8,461
  • 6
  • 37
  • 49
8

Jquery data automatically parses JSON strings into objects. You just have to follow the directions from jQuery.parseJson()

http://api.jquery.com/jquery.parsejson/

Changing your Options From data-options="{maxDate:'0'}" to data-options='{ "maxDate": 0 }' Works wonders

EDIT: 12/28/2015

Since in XHML you don't want to use single ' for properties, you can do the oposite and then replace the single quotes with double then parse the json response. { 'maxDate': 0 } then .replace(/'/g, '"') and use $.parseJSON()

$("input.dataWithoutOptions").each(function() {
   $(this).datepicker({
     maxDate: '0'
   })
 });

 $("input.data").each(function() {
   var dateOptions = $.parseJSON($(this).data('options').replace(/'/g, '"'));
   $(this).datepicker(dateOptions);
 });
input {
     display: block;
     margin: 10px 0 20px;
     padding: 5px;
   }
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/themes/smoothness/jquery-ui.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.11.3/jquery-ui.min.js"></script>

This has options attr:
<input class="data" type="text" data-options="{ 'maxDate': 0 }" />This is just a date pick:
<input class="dataWithoutOptions" type="text" />

EDIT: 12/30/2015

@Lidaranis : Brings up a good point.

You can use escaped characters to avoid regex and parsing json. {&quot;maxDate&quot;:0}

$("input.dataWithoutOptions").each(function() {
  $(this).datepicker({
    maxDate: '0'
  })
});

$("input.data").each(function() {
  var dateOptions = $(this).data('options');
  $(this).datepicker(dateOptions);
});
input {
  display: block;
  margin: 10px 0 20px;
  padding: 5px;
}
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/themes/smoothness/jquery-ui.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.11.3/jquery-ui.min.js"></script>

This has options attr:
<input class="data" type="text" data-options="{&quot;maxDate&quot;:0}" />This is just a date pick:
<input class="dataWithoutOptions" type="text" />
Roger
  • 3,226
  • 1
  • 22
  • 38
  • Sorry, but I'll never use single marks for an xHtml attribute. http://stackoverflow.com/questions/242766/is-it-correct-to-use-single-quotes-for-html-attributes – Vixed Dec 19 '15 at 18:00
  • @Neoptt, I really like your answer, but can you please fix the single and double mark problem?! – Vixed Dec 28 '15 at 15:45
  • I'm pretty sure that this is the simplest answer if you are using jquery. Just do a string replace the quotes and parse the json response, after that it's all downhill from there. – Roger Dec 28 '15 at 17:22
1

the datepicker function needs an object and currently you are passing a string hence you get the error.

Rovi
  • 259
  • 1
  • 3
0

Try this,

Option - 1

change JavaScript to

$("input.data").each(function(){
  var dateOptions=$(this).data('options');
  var options = dateOptions.split(', ');
  var obj = {};
  options.forEach(function(opt) {
      var item = opt.split(':');
      obj[item[0]] = item[1];
  });

  $(this).datepicker(obj);
});

and change html to

<input class="data" type="text" data-options="maxDate:'0'"/>

And no eval()

see the javascript fiddle https://jsfiddle.net/exfLf6o9/7/

Option - 2

JavaScript

$("input.data").each(function(){
  var dateOptions=$(this).data('options');
  dateOptions = dateOptions.substring(1,dateOptions.length-1);
  var options = dateOptions.split(', ');
  var obj = {};
  options.forEach(function(opt) {
      var item = opt.split(':');
      obj[item[0]] = item[1];
  });

  $(this).datepicker(obj);
});

and leave html as it is

see the js fiddle https://jsfiddle.net/exfLf6o9/8/

Option - 3

change html to

<input class="data" type="text" data-options='{"maxDate":"0"}' />

and in javascript

$("input.data").each(function(){
  var dateOptions=$(this).data('options');
  $(this).datepicker(dateOptions);
});

using eval() is not recommended in JavaScript

Please see the fiddle https://jsfiddle.net/exfLf6o9/5/

Mohammed Safeer
  • 20,751
  • 8
  • 75
  • 78
0

data() returns a string when datepicker() is expecting an object. The solution is to convert the string to an object:

$("input.data").each(function(){
    var dateOptions = $(this).data('options');
    var dateOptionsAsObject = JSON.parse(dateOptions.replace(/([\w|\-|\_]+:)/g,"\"$1\":"));
    $(this).datepicker(dateOptionsAsObject);
});
Samuel
  • 2,106
  • 1
  • 17
  • 27
0

Wanted to throw out the lazy-loading technique, since no one mentioned it.

<div class="data" data-max-date="0"></div>

$.data() will automatically camelCase your data attributes and attempt to type cast. i.e. the above html attribute data will become: { maxDate: 0 }

$('.data').each(function(){
  $this = $(this);
  $this.datepicker($this.data());
});
jtrumbull
  • 818
  • 9
  • 19