Preserve data when converting a jQuery object to html - javascript

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)
}
}]

Related

Laravel js DataTable: how do I assign a value from js back to the .blade?

I have these rows:
each row is being outputted by the DataTable plugin within app.js
my target is this particular value, ${row.category_id}
let TABLE = $('#categoryList').DataTable({
{ data: 'id', name: 'id', width: '10%', orderable: false, searchable: false,
render: (data, type, row) =>{
let html = "";
if(row.category_name && row.category_name.toUpperCase() !== "GENERAL"){
html += `<ul class="list-inline no-margin">`;
html += `<li class="list-inline-item">
<button type="button" value="${row.category_id}" class="edit_category btn btn-outline-secondary"><i class="fas fa-edit" aria-hidden="true"></i> Edit</button>
</li>`;
html += `</ul>`;
}
return html;
}
}
});
now I have this blade file, index.blade.php that is connected to app.js using:
<script src="{{asset('/modules/bbr-category-configuration/js/app.js')}}"></script>
What I need to resolve is the constant below:
#section('scripts')
<script type="text/javascript">
const SELECTED_CATEGORY_ID = 1;
</script>
#endsection
by default it is set as 1, but this needs to changed each time the 'Edit' button is clicked (refer to the screenshot). Once the button is clicked, I need to get ${row.category_id} and assign it to the const SELECTED_CATEGORY_ID. What is the correct way of doing this?
TLDR: how do I pass a value from .js back to .blade.php?
What I tried:
my first obstacle is to get the value from ${row.category_id} on click, but here is where I got stuck
$(document).on('click', '.edit_category', function () {
console.log(${row.category_id});
});
I cannot console.log (to test if I got the correct variable) outside the DataTable because it cannot be read, or do it inside toe columns because it is not the right syntax.
please feel free to ask for any clarifications.
First of all, if your variable's data will change during the process then it is not const it should be declared as let. You should know the difference between var let and const.
And you can use data-* attributes in the edit button so you can easily fetch the category_id when that button is clicked eg:
<button type="button" data-category=`${row.category_id}`class="edit_category">Edit</button>
Then on click event, you can get that data using
$('.edit_category').click(function (e) {
SELECTED_CATEGORY_ID = $(this).data('category');
});
You can fetch the value attribute of the button too using jquery. But generally, I don't use that. Or I haven't seen much usage of that too. You can try it like this too
$('.edit_category').click(function (e) {
SELECTED_CATEGORY_ID = $(this).value;
});

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(';');
}

pass an object in jqgrid

I am using jqgrid on my form and I am creating the column delete and want to send the object in javascript function, the code is following
{
name: "action",
align: "center",
sortable: false,
title: false,
fixed: true,
search: false,
formatter: function (cellValue, options, rowObject) {
debugger;
var markup = "<a title=\"%ToolTip%\" href=%Href%;>%Text%</a>";
var replacements = {
"%Text%": "<i class='fa fa-trash' style='color:black'></i>",
"%ToolTip%": UserRoles.messages && UserRoles.messages.ClickHereToDelete
? UserRoles.messages.ClickHereToDelete : "",
"%Href%": "javascript:UserRoles.deleteUserRoles(" + rowObject + ")"
};
markup = markup.replace(/%\w+%/g, function (all) {
return replacements[all];
});
return markup;
}
}
I want to send the object in the function deleteUserRole by this line
"%Href%": "javascript:UserRoles.deleteUserRoles(" + rowObject + ")"
but it is giving me output
<a title="" href="javascript:UserRoles.deleteUserRoles([object" object]);=""><i class="fa fa-trash" style="color:black"></i></a>
can any one help me
Mostly one don't need to create such custom formatter and one can use just formatter: "action" with the corresponding parameters.
It's important to understand that the goal of formatter is providing the HTML fragment which will be placed in cells (in <td>) of the column. The rowObject are typically the input data of the row which format depend on many factors.
What you probably need is to use options.rowId as parameter of UserRoles.deleteUserRoles function. Inside of the function you can use getRowData to get the data based on the rowid.
I would recommend you to read the answer and all old answer referenced i the answer. It shows that one can just use place "<a href='#'><i class='fa fa-trash' style='color:black'></i></a>" by custom formatter **without using any javascript:UserRoles.deleteUserRoles(...) fragment. Instead of that one can implement beforeSelectRow callback which tests in which column the user clicked. If the user clicked on the <a> of "action" column then one can do some custom action. The way is more effective because one don't need bind global function to every <a> element of the column. One can simplify the content of the column by removing <a> and holding only <i class='fa fa-trash' style='color:black'></i> inside of the column. The code of beforeSelectRow callback will be the same.

Dojo grid: accessing another attribute from a formatter

I have a Dojo EnhancedGrid. Suppose in one column I want to display the employee's name as a link, and aart of the URL contains must employee ID.
The row in the grid:
structure:[
{name:"Name", field:"name", datatype:"string", formatter:createLink},
...
The formatter:
var createLink = new function(name){
return "" + name + "";
}
How do I get the value of employeeID in the formatter?
Completely different approaches very welcome as well!
p.s. if it's relevant, the grid is using an ObjectStore wrapping an instance of JsonRest.
function formatter(value, idx) {
var gridRow = theGrid.getItem(idx);
//gridRow["property"]; //some property from the store
}
This works for me. Hope it helps.

How to dynamically construct html tag attriburtes with json data?

I am having (Strigified) json data in a variable called test. I am constructing html elements dynamically and also I want json data to be inserted in an element attribute.
var templateHtml = "":
$.each(loopValues, function(Key, Value) { // Loops which constructs dynamic data
var test = '{"type": "page"}'; // this is the json data which need to be appended as data-all attribute value.
templateHtml = templateHtml.concat("<a data-all="+ test +" href='javascript:;' class='icon' id='TestTt'></a>");
}
$("#sortable1").html(templateHtml);
After executing these lines, when I see the constructed element, It is totally scrambled. How to get a well formatted json data in a element attribute ?
I do not want to append json data on attribute using jquery after constructing html. I want this functionality at html construction time.
I refered
http://gabrieleromanato.name/jquery-binding-animation-data-to-elements-with-json/
http://api.jquery.com/jQuery.parseJSON/
Any Idea ?
First, your code miss some syntax element :
var templateHtml = ""; // use ; not :
$.each(loopValues, function (Key, Value) { // Loops which constructs dynamic data
var test = '"{type": "page"}'; // this is the json data which need to be appended as data-all attribute value.
templateHtml = templateHtml.concat("<a data-all=" + test + " href='javascript:;' class='icon' id='TestTt'></a>");
}); //close the loop call
Then you need to add single quotes around your test variable when you append it. I suggest you choose where to use single quotes or doubles and stick to the choice permanently. I personnally use double quotes in HTML and single quotes in JS :
var templateHtml = '';
$.each(loopValues, function (Key, Value) { // Loops which constructs dynamic data
var test = "{type: 'page'}"; // this is the json data which need to be appended as data-all attribute value.
//since its JSON i use single quote inside but double outside.
templateHtml = templateHtml.concat('<a data-all="' + test + '" href="javascript:;" class="icon" id="TestTt"></a>');
});
FIDDLE here
What you need is creating elements with jQuery with json as parameters.
For example creating a simple table
var $table = new $('<table>', { 'cellpadding' : '5', 'cellspacing' : '4' });
var $tr = new $('<tr>');
var $td = new $('<td>', { 'class' : 'test' });
$td.text('cell contents');
$tr.append($td);
$table.append($tr);
$('body').append($table);
You can keep your json in DOM without data- attribute, just use:
$("#sortable1").html("<a href='javascript:;' class='icon' id='TestTt'></a>");
$( "#sortable1 > a" ).data( 'all', test );
According to jQuery .data() API. Data value can be any JavaScript type.
To get this JSON you will need just to write:
console.log( $( "#sortable1 > a" ).data( 'all' ) );
UPDATE:
But better is to add data at creation proccess:
$.each(loopValues, function(Key, Value) { // Loops which constructs dynamic data
$( "#sortable1" ).append( $( "<a/>" ).addClass( "icon" ).data( "all", {"type": "page"} ).attr( "id", "TestTt" ) );
});

Categories