jQuery .data() is not actual after adding new values - javascript

I've got div like
<div data-a="aa"> </div>
Then I'm getting its data with:
var data = $("div").data();
And its working fine. Then I'm adding new data like this via data- attribute:
$("div").attr("data-b", "bb");
Then I'm getting data again like
var updatedData = $("div").data();
However, the new value ( data-b attr with bb value ) is not there. Why is that? (I want to manage data via data- attributes)
Fiddle playground
Using attributes is suitable in my case, so I dont want to use .data("key", "val"). data- attributes are valid anyway
Interesting thing is that when I add data- attribute before first call of .data() - it works ok. Is there a way to ignore or 'rebuild' cache of data then? example here

Use .data("key","value") to set the value
$("div").data("b", "bb");
Also use .data("key") to get the value
var data = $("div").data("b");

When you use the data() api, jquery uses an internal private data structure to store the data so the attribute value is not updated.
When you use the data api, there is no need to use the data- prefix.
So once you use the data api to read the values the attribute values are copied to the internal data structure thereafter any changes done to the attribute will not be reflected in the data api.
Demo: Fiddle

There are two ways to add data to an element either you can use data() function by jQuery or you can manually add the 'data-attribute'
The issue you're facing is you can always GET as well as SET the data-attribute's value with data() function. But the attribute SET by this function won't be visible in HTML file.
In the below, 'data-c' won't be visible in the HTML file.
<div class='bar' data-a='avalue' data-b='bvalue'></div>
<script>
console.log($( "div" ).data());
$( "div" ).data('c','cvalue');
console.log($( "div" ).data());
</script>

Try using dataset
var article = document.querySelector('#div1'),
updatedData = article.dataset;
Demo
Reference JavaScript Access

Related

Get Data Attribute Value Without CamelCasing

Is it possible to pull out a data attribute value without grabbing the data attribute via camel case?
Example: Take this button:
<button id="my-button" type="button" data-some-url=<%=some_dynamic_path%>>Lookup</button>
When this button is clicked I want to do some ajax stuff. Currently I only know how to grab the data attribute value by camel casing:
$("#my-button").on("click", function(){
url = $(this).data("someUrl");
});
Instead I would prefer to grab the data attribute value like so, but of course it doesn't work:
url = $(this).data("some-url");
Question: Is there some way I can grab the data attribute value by keeping the hyphens in there?
Update:
I made a simple typo. The second version does in fact work:
url = $(this).data("some-url");
That will successfully get you the data attribute value.
Just pass the name as a string to the data method.
$('#my-button').data('some-url')
You could ignore it's data-semantics and treat it like any other attribute:
url = $(this).attr( 'data-some-url' );

Multiple search by ID. Search not knowing full ID. Sapui5

I was wondering if there was any option to search an element by its id but not knowing the full ID, only part of it. So I could find an element without knowing its full ID or find multiple elements with similar IDs.
For example if I knew I had 3 objects with the followings ID:
"objectID1" "objectID2" and "objectID3".
Could I something like:
getElementByID("objectID*")
I have tried it in JavaScript using: input[id*='PART_OF_ID_I_KNOW']
But it returns an HTML object and I need it for SAPUI5.
Could I use something like:
var myControl = sap.ui.getCore().byId('myId');
But not having to match the full ID (myID)? Thanks.
Though I would not recommend this but it's possible in a way as you describe it.You could look for elements with similar ID with jQuery, get the element's ID and pass it to sap.ui.getCore().byId();
var aElements = $("div[id*='PART_OF_ID_YOU_KNOW']");
//Lets say the first element returned is the one belonging to your control
var oControl = sap.ui.getCore().byId(aElements[0].id); //If the element is a SAPUI5 control, you should get it.
Why do you need to do this? Is it because you want to access controls (with prefixed IDs) inside your views and fragments? Did you give an ID of "myControl" to the control, but sap.ui.getCore().byId("myControl") doesn't work as the framework added a prefix to it?
If yes, the only reliable way to get a reference to your control is by using the framework provided methods in MVC views and controllers and in fragments.
If you have a control called "myButton" in your view, do this.byId("myButton") or this.getView().byId("myButton") from the controller to get a reference to your control.
If you have a control called "myButton" in a fragment that you embedded in your view via sap.ui.xmlfragment("", "myFragment.fragment.xml"), then use sap.ui.core.Fragment.byId("<prefix>", "myButton") to access it.
Whatever you do, don't make assumptions on how the framework creates these prefixed IDs. These are not documented and can change.
when you use `var myControl = sap.ui.getCore().byId('myId');`
it won't work.It is because when you try to get control by sap.ui.getCore() sapui5 automatically concat extra string to Your id egsap.ui.getCore().byId('xml0--myId') and if you have provided viewId in manifest then while rendering control it uses that. eg
sap.ui.getCore().byId('yourManifiestId--myId')

SAPUI5 bindAggregation from XML Model by Attribute Name

I do have a XML-Model which looks like this:
I would like to add the sap.m.ComboBox control to my UI. I want the value from attribute Name from the Member tag. I am able to do so with this code:
new sap.m.ComboBox({
items : {
templateShareable : true,
path : "metadata>/edmx:DataServices/edm:Schema/edm:EnumType/0/edm:Member",
template : new sap.ui.core.ListItem({
text: "{metadata>#Name}"
})
}
})
BUT, instead of selecting the EnumType hard by calling it's index (edm:EnumType/0/), I would rather like to select it by it's attribute Name. E.g. something like this would be nice:
"metadata>/edmx:DataServices/edm:Schema/edm:EnumType(Name=RoleCategory)/edm:Member"
Does anyone know how to do so? Any idea is highly appreciated.
There is no such thing in the path syntax. You can see in the OpenUI5 code that the path supports only
attributes #
text()
elements by tag name
array indices.
You cannot use element binding to filter either as element binding does not support filtering and sorting.
You could however attach to the models requestCompleted or metadataLoaded events and update the binding path or copy the data to a separate model.
If you want it dirty you could use a container control, bind it to /edmx:DataServices/edm:Schema/edm:EnumType with your ComboBox as template and apply an appropiate filter. You then have to use a relative path in you Combobox. :)

Identity selectors in jQuery returning arrays

Suppose I have a div tag like this:
<div id="group-dialog" class="modal-dialog">
Now I want to grab it as a jQuery object (in this case so I can run .dialog()).
When I try this:
var gDialog = $('#group-dialog');
I get an array back (!!).
Why am I getting an array? Isn't the point of having an ID attribute that there's only one? I can see getting multiple p's or .my-css-thing back ...
Next question:
I have this array with 1 object in it that I now want to access as a jQuery object.
When I do this:
$(gDialog[0])
And pull it up in F12, I still have an array!! I thought I de-referenced the array already by picking the first element.
This doesn't seem to help either:
var gDialog = $('#group-dialog:first');
This is basic, but I run into this problem a lot. It seems like it used to be a lot simpler!
What is the best way to access this DOM element as a jQuery object?
Answer 1
jQuery selectors always return arrays.
Selection with id attribute is a particular use case and ideally the result should be unique. However, there is nothing preventing you from having duplicated ids in a HTML document (although this is bad practice).
Answer 2
The following code will get you the first element as a DOM object:
var gDialog = $('#group-dialog')[0];
Note: you may want to check the size of the return array first.
As far as I know, there is no way to transform this DOM element back to a jQuery object. The standard use case would be to directly used $('#group-dialog') and asume that it is found and unique.
Try using .get(). Though I'm not sure it will work with dialog()
Retrieve the DOM elements matched by the jQuery object.
var gDialog = $('#group-dialog').get();
If you're trying to grab it to use it on a dialog, you can just put
$(document).ready(function(){
$('#group-dialog').dialog({put options here})
});

Best Practice with jQuery and AJAX calls

I have a question about best practices when using jQuery/JavaScript/Ajax. Lets say that I have some tasks and there is a calendar for every task. The User is able to click on a day in a task calendar and book the task at the specific day via AJAX. I have to store the date and the ID of the task somewhere and i am using really bizarre IDs for that such as:
<span class="day_field" id="date_13-02-2013_task_4">13.02.2013</span>
Then i just attach an listener like this:
$('.day_field').on('click',function(){
var date = $(this).id.split('_')[1];
var task_id = $(this).id.split('_')[3];
//place for some validation
$.post('book_task.php',{task_id: task_id, date: date},function(data){
//something cool with the result
});
});
My question is: Is this the right way how to do it? I am not pretty sure, because the IDs can be really long + it contains ID in database which is not probably save at all.
Thanks!
T.
Use HTML5 data attributes:
<span class="day_field" data-date="13-02-2013" data-task="4">13.02.2013</span>
$('.day_field').on('click',function(){
var date = $(this).data("date");
var task_id = $(this).data("task");
//place for some validation
$.post('book_task.php',{task_id: task_id, date: date},function(data){
//something cool with the result
});
});
The right wayA better way to do it would be to store the data in either data attributes, or make the span an anchor tag and store the param string desired in the href attribute.
<span class="day_field" data-date="13-02-2013" data-task="4>13.02.2013</span>
or
<a class="day-field" href="?task_id=4&date=13-02-2013">13.02.2013</a>
with this for the anchor tag:
$('.day_field').on('click',function(e){
e.preventDefault();
$.post("foo.php",this.href,handler);
});
Instead of an ID, you can use custom data attributes, like this:
<span class="day_field" data-date="date_13-02-2013_task_4">13.02.2013</span>
And then you can access the value like this in jQuery:
$(".day_field").data("date");
Exposing the actual ID of something in your database is only as insecure as your database.
Using the id of the element seems fine to me, too, if it uniquely identifies a thing. Using the data attributes is a possibility to save on splitting logic if you like, but you could still use id in tandem.
Conventionally speaking, this is very tame code compared to much of what jQuery is.
One more elegant way to associate data to an element is to use jQuery's data. However, I would consider building a jQuery plugin and using one instance of it for each task. A plugin encapsulates all of the data it needs, so you wouldn't need to store it tied to the element, which is not great.

Categories