Adding json object via .data() to dynamically added td via jquery - javascript

I am using HTML, CSS and JQuery/JavaScript to create a table which its td is populated during runtime. Depending on the data returned via Ajax, only some tds are populated. I have added click and doubleclick event to the populated tds. For doubleclick event, I need to call a function and pass JSON object to it. The JSON data are something like below or here
{
"is_active": true,
"timeslots": [
{
"department": "department01",
"end_time": "13:00:00",
"id": 3,
"start_time": "09:00:00",
"number": 1
}
//... and other timeslots
}
Below are the code snippets:
HTML:
...
<tr id="department_row">
<td class="first-column">Department</td>
<!-- TODO: To add cells via JQuery/JavaScript-->
</tr>
JavaScript/JQuery:
$.getJSON(
"http://url_for_the_data"
).done(function(data) {
let allDepartmentData = data['timeslots']
let scheduleRow: string
for (let singleData of allDepartmentData) {
scheduleRow += '<td id="td_schedule_'+ singleData.id +'>'+ singleData.trolleys +'</td>'
// The part I want to add the data to the td
$('#td_schedule_' + singleData.id).data('slot', singleData);
}
$('#department_row').append(scheduleRow)
})
Then, after the page is loaded, in Chrome DevTool, I accessed via its console $('#td_schedule_3').data('slot') but it gave me undefined. As written in my first paragraph, the purpose is when the td with the data is double clicked, the JSON object (i.e. department, end_time, id, start_time and number) will be passed to a function which will call up an Edit Modal with the data from JSON object. For simplicity, I do not put in the codes related to the double click event and edit modal.
Can anyone help with this? Thanks.

Related

Preserve data when converting a jQuery object to html

I have an html element which is created in JavaScript.
This element should also save one object as a data- attribute and then get converted to pure html.
My problem is that the data- attribute vanishes after accessing the prop("outerHTML").
Here is what I mean:
let obj = $("<i>TEST</i>");
obj.data("key", "value");
let html = obj.prop("outerHTML");
console.log("DATA: " + obj.data("key")); //gives value
console.log("HTML: " + html); //gives <i>TEST</i>
I also tried to directly enter the data- attribute, but the quotes a making trouble.
I tried:
let dataJSON = JSON.stringify(data);
let obj = $('<i data-test=' + dataJSON + '</i>'
My goal is to generate a dataTable cell which needs to contain some data to handle clicks on it. The whole thing looks like this:
columns: [
data: "notice_id", render: function (data, type, row) {
let html = $('<i class="edit-button fas fa-pencil-alt"></i>');
html.data("notice", row);
return html.prop("outerHTML");
}]
edit:
I should have written that I know, that jQuery doesn't really alter the data- attribute. I somehow hoped that it would add it anyways when I access the outer html.
However, the linked question doesn't really give an answer on how to make it better (except writing it directly which causes problems with other than simple string data).
You can use the createdCell callback if you want more post processing, and enrich the <i> with data() in there:
columns: [{
data: "notice_id",
render: function(data, type, row) {
//no need for constructing jQuery instances here
return '<i class="edit-button fas fa-pencil-alt"></i>'
},
createdCell: function(td, cellData, rowData, row, col) {
$('i', td).data('notice', rowData)
}
}]

AngularJS - Get printed value from scope inside an attribute?

I'm currently working on an AngularJS project and I got stuck in this specific requirement.
We have a service that has all the data, DataFactoryService. Then, I have a controller called DataFactoryController that is making the magic and then plot it in the view.
<div ng-repeat = "list in collection">
{{list.name}}
...
</div>
Now, we have a requirement that pass multiple data into one element. I thought an "ng-repeat" would do, but we need to have it inside an element attribute.
The scenarios are:
At one of the pages, we have multiple lists with multiple data.
Each data has a unique code or ID that should be passed when we do an execution or button click.
There are instances that we're passing multiple data.
Something like this (if we have 3 items in a list or lists, so we're passing the 3 item codes of the list):
<a href = "#" class = "btn btn-primary" data-factory = "code1;code2;code3;">
Submit
</a>
<a href = "#" class = "btn btn-default" data-factory = "code1;code2;code3;">
Cancel
</a>
In the example above, code1,code2,code3 came from the list data. I tried several approach like "ng-repeat", "angular.each", array, "ng-model" but I got no success.
From all I've tried, I knew that "ng-model" is the most possible way to resolve my problem but I didn't know where to start. the code below didn't work though.
<span ng-model = "dataFactorySet.code">{{list.code}}</span>
{{dataFactorySet.code}}
The data is coming from the service, then being called in the controller, and being plot on the HTML page.
// Controller
$scope.list = dataFactoryService.getAllServices();
The data on the list are being loaded upon initialization and hoping to have the data tags initialized as well together with the list data.
The unique code(s) is/are part of the $scope.list.
// Sample JSON structure
[
{ // list level
name: 'My Docs',
debug: false,
contents: [ // list contents level
{
code: 'AHDV3128',
text: 'Directory of documents',
...
},
{
code: 'AHDV3155',
text: 'Directory of pictures',
...
},
],
....
},
{ // list level
name: 'My Features',
debug: false,
contents: [ // list contents level
{
code: 'AHGE5161',
text: 'Directory of documents',
...
},
{
code: 'AHGE1727',
text: 'Directory of pictures',
...
},
],
....
}
]
How can I do this?
PLUNKER -> http://plnkr.co/edit/Hb6bNi7hHbcFa9RtoaMU?p=preview
The solution for this particular problem could be writing 2 functions which will return the baseId and code with respect to the list in loop.
I would suggest to do it like below
Submit
Cancel
//inside your controller write the methods -
$scope.getDataFactory = function(list){
var factory = list.map( (a) => a.code );
factory = factory.join(";");
return factory;
}
$scope.getDataBase= function(list){
var base= list.map( (a) => a.baseId);
base= base.join(";");
return base;
}
Let me know if you see any issue in doing this. This will definitely solve your problem.
You don't really have to pass multiple data from UI if you are using Angular.
Two-way data binding is like blessing which is provided by Angular.
check your updated plunker here [http://plnkr.co/edit/mTzAIiMmiVzQfSkHGgoU?p=preview]1
What I have done here :
I assumed that there must be some unique id (I added Id in the list) in the list.
Pass that Id on click (ng-click) of Submit button.
You already have list in your controller and got the Id which item has been clicked, so you can easily fetch all the data of that Id from the list.
Hope this will help you... cheers.
So basing from Ashvin777's post. I came up with this solution in the Controller.
$scope.getFactoryData = function(list) {
var listData = list.contents;
listData = listData.map(function(i,j) {
return i.code;
});
return listData.join(';');
}

Use AJAX to load content to a jQuery UI dialog

On my site, I have a bunch of profile previews that are being generated by running JSON data through a mustache.js template.
Here's the template:
<script id="profile-preview-template" type="text/template">
<div class="col-sm-3">
<a style="display:block">
<div class="profile-preview">
<img class="img-responsive img-circle center-block" width="200px" src="{{img_url}}" alt="Photo of {{first_name}} {{last_name}}" />
<h1>{{first_name}} {{last_name}}</h1>
<h2 class="text-muted">{{major}}</h2>
<h3 class="text-muted">Cohort {{cohort}}</h3>
</div>
</a>
</div>
</script>
The profile preview shows select info from the JSON info like first_name, last_name, etc.
Here's the format of the JSON data:
{
"profiles": [
{
"first_name": "Robert",
"last_name": "Hosking",
"img_url": "img/about/hackbert.jpg",
"major": "Computer Science",
"cohort": 12,
"bio": "some info",
"linkedin": "some url",
"home_town": "some place",
"status": "Student"
},
{
"first_name": "Jimmy",
"last_name": "Harval",
"img_url": "img/about/hackbert.jpg",
"major": "Chemistry",
"cohort": 13,
"bio": "some info",
"linkedin": "some url",
"home_town": "some place",
"status": "Student"
}
]
}
However, when one of the previews is clicked, I'd like to make a jQuery UI dialog modal popup containing all of the info in the JSON data (not just the data displayed in the preview).
My question is how do I get a reference as to which profile preview was clicked so I know where in the JSON file to look to get the rest of the information.
I made some slight changes to your HTML and template script.
<div class="profile-full"></div>
<div class="preview"></div>
<script id="profile-preview-template" type="text/template">
<div class="col-sm-3">
<a style="display:block">
<div class="profile-preview">
{{#profiles}}
<img class="img-responsive img-circle center-block" width="200px" src="{{img_url}}" alt="Photo of {{first_name}} {{last_name}}" />
<h1 id="whichProfile">{{first_name}} {{last_name}}</h1>
<h2 class="text-muted">{{major}}</h2>
<h3 class="text-muted">Cohort {{cohort}}</h3>
{{/profiles}}
</div>
</a>
</div>
</script>
As you can see, 2 divs for demonstration purposes.
.profile-full Where the contents of the correct object is output using JSON stringify. What gets output can of course be changed, this is just to show that the correct object is selected.
.preview Where the preview profiles are generated.
I also added the opening and closing {{#profiles}} {{/profiles}}
profile is derived from what is set in the beginning of your json.
"profiles": [
We assume that you have correctly linked the jQuery and mustache.js libraries. Name your json file from your post as data.json
You must also link the .js file below. I have named it main.js.
$(function() {
$.getJSON('data.json', function(data) {
var template = $('#profile-preview-template').html();
var html = Mustache.to_html(template, data);
$('.preview').html(html);
allProfiles = data.profiles;
lookup = [];
for(i=0;i<data.profiles.length;i++) {
lookup.push(data.profiles[i].last_name);
};
});//getJSON
$(document).on('click', '#whichProfile', function() {
var whichName = $(this).text().substr($(this).text().indexOf(" ") + 1);
var i = jQuery.inArray(whichName, lookup);
$('.profile-full').html(JSON.stringify(allProfiles[i]));
});
});//document ready
So what's happening here?
$(function() {
$.getJSON('data.json', function(data) {
var template = $('#profile-preview-template').html();
var html = Mustache.to_html(template, data);
$('.preview').html(html);
After our document.ready shorthand, we GET the contents of the data.json, and hold it in data. Then we put the contents of html into the div with a class of preview, as we have formatted it according to the template script.
allProfiles = data.profiles;
lookup = [];
for(i=0;i<data.profiles.length;i++) {
lookup.push(data.profiles[i].last_name);
};
});//getJSON
Next we'll create an array called lookup which contains only the last_name data from our json. This will make it possible and fast to get the reference as to which profile preview was clicked.
If you only have a few names, using the last name is fine, but use a unique identifier if the amount of profiles grows (So overlapping last names doesn't occur). Consider adding a unique id, or email to your json.data.
Then close your getJSON.
$(document).on('click', '#whichProfile', function() {
var whichName = $(this).text().substr($(this).text().indexOf(" ") + 1);
var i = jQuery.inArray(whichName, lookup);
$('.profile-full').html(JSON.stringify(allProfiles[i]));
});
});//document ready
Here on clicking a name will get the .text of what's on our page. We will convert it so it's only the last name (strip everything before the space).
We then search for this last name within the lookup array and return its index. Now that we have this index we can use it to get any value within the json relative to the index. In this example we just put the entire stringified contents of the relevant object into our profile-full div
Finally we close our document.ready.
Try clicking on a name (Can be the first or last name). We could of course put anything from that relevant object anywhere else. For example:
remove the line
$('.profile-full').html(JSON.stringify(allProfiles[i]));
and replace it with
alert(allProfiles[i].first_name + ' ' + allProfiles[i].last_name +
' is studying ' + allProfiles[i].major + ' as their Major');
Now clicking on a name will get a pop up, stating their full name and which Major they are studying.
In your template, give each <a> element an id attribute equal to the index of the corresponding profile in the JSON array.
Then, you can give the <a> element an onclick method such as foo(this), because this will pass the element to the function. In your function, you can retrieve the id with $(elem).attr("id"), where elem is the function parameter. Now you have the index of the profile, so it should be easy to retrieve the profile's information.

angular scope variable is not visible inside anchor tag

Hello I am newbie to Angular and tried to call a controller method with a hyperlink by following way:
{{item.contractnum}}
Where item.contractnum is a scope variable which is visible when I pull it out from 'a' tag but inside the tag its not visible, also I want to pass it back to controller method getAssetDetail but can't figure out how to accomplish it. Please suggest.
EDIT:
View:
<tbody>
<tr ng-repeat="item in pagedItems[currentPage] ">
<td>contract number {{item.contractnum}} <br /> Serial Number:{{item.serialNum}} </td>
</tr>
</tbody>
Controller:
$scope.getAssetDetail = function (contractNum) {
//My Code Here
}
pagedItems=[{"contractnum":"123", "serialNum":"ABC1" },
{"contractnum":"121", "serialNum":"ABC2" },
{"contractnum":"124", "serialNum":"ABC3" },
{"contractnum":"125", "serialNum":"ABC4" }
]
if you realy have pagedItems like
pagedItems=[{"contractnum":"123", "serialNum":"ABC1" },
{"contractnum":"121", "serialNum":"ABC2" },
{"contractnum":"124", "serialNum":"ABC3" },
{"contractnum":"125", "serialNum":"ABC4" }
]
so you wrong use ngRepeat, because pass to it simple object like pagedItems[0]
{"contractnum":"123", "serialNum":"ABC1" }
so item in this case is 123,ABC1 that realy don't have property contractnum and others
for solving you can use
ng-repeat="item in pagedItems"
or save in pagedItems arrays of object like [[{},...],[{},...],[{},...]]
or use filter like limitTo for select only needed element in pagedItems
If your pagedItems data is meant to be just for one page of data, then you need to change the ng-repeat line to:
<tr ng-repeat="item in pagedItems">
If your pagedItems data is meant to be all the data for every page, then you need to change your pagedItems data structure to be an object with properties for each page number like:
pageItems = {
"1": [{"contractnum": "121"}, ... etc],
"2": [{"contractnum": "131"}, ... etc]
... etc ...
}
or as an array of arrays where the index in the outer array is the page number (or perhaps pagenumber - 1) and the inner arrays are arrays of objects for each page like:
pageItems = [
[{"contractnum": "121"}, ... etc],
[{"contractnum": "131"}, ... etc]
]
Your existing ng-repeat line should then work.

Creating a dropdown menu with JSON input stored in a txt file

I am trying to create a drop-down list with JSON data stored in a txt file. My main issue is reading the data (I saved the data which I retrieved from an API into a txt file because it is a large amount of data and I wanted to save time by not having to make a request to the API every time the data is needed)
*As a side note, not entirely sure that getting the data in the form of JSON is the best option. Other options supported by this API are: CSV, JSONP, serialized PHP, and XML (if one of those would be easier)
Here is the form of the JSON data (stored as a string in classes.txt):
{
"classes": [
{
"cat_num": "0001",
"field": "OEB",
"number": "363",
"title": "Plant Diversity and Evolution"
},
{
"cat_num": "0002",
"term": "FALL",
"bracketed": false,
"field": "OEB",
"number": "364",
"title": "Ecological Physiology of Microbes"
}
]
}
Here is my code for trying to populate the dropdown menu with this txt file thus far
$(document).ready(function(){
var url = "classes.txt";
$.get(url, function(data) {
var obj = eval('(' + data + ')');
$.each(obj, function(i, option){
$('#department').append($('<option/>')
.attr("value",option.cat_num)
.text(option.field));
);
);
});
I've also realized that I need to somehow make sure that "field" is unique in my drop down (i.e. if 3 classes are of the field "OEB", I just want OEB to appear in my drop down once, not 3 times)
Thanks in advance for any help you might be able to provide!
here this could help
$(document).ready(function(){
$.getJSON('classes.txt', function(data) {
$.each(data, function(i, option){
console.log(option.title)
$('#department').append($('<option/>').attr("value",option.cat_num).text(option.title));
});
});
});

Categories