I am creating a html element using javascript:
html_info += '<div class="row"><h4>'+ i +'. Patient: '+ key +'</h4>Date of birth: '+info[0]+'<br> Occupation: '+info[1]+'<br> Date of Test: ' + info[2]+ '<script type="text/javascript"> draw_chart(' + patient_test_info[key].right_eye +' ); </script></div>';
document.getElementById('patient_display').innerHTML += html_info;
It creates the element properly and displays the information stored in info array, but call to the draw_chart() function fails. I printed the contents of patient_test_info[key].right_eye using console.log before passing it as an argument and the contents of the variable are fine. But checking the html elements displays that patient_test_info[key].right_eye is not passed correctly and are just empty objects.
<script type="text/javascript"> draw_chart([object Object],[object Object],[object Object],[object Object] ); </script>
My draw_chart() function must draw the chart in the same div as the one used to display info content. On calling it independently, it does not recognise the newly created div and thus does not display anything.
function draw_chart(data) {
var chart = d3.cloudshapes.barChart()
.width(800).height(800);
for(var i=0; i<data.length; i++) {
var temp_value = data[i];
d3.select("#row")
.datum(temp_value)
.call(chart);
}
}
What is the right way of calling the function using an argument ?
What adeneo is saying is if you call the function directly it should work, like this:
html_info += '<div class="row"><h4>'+ i +'. Patient: '+ key +'</h4>Date of birth: '+info[0]+'<br> Occupation: '+info[1]+'<br> Date of Test: ' + info[2] + draw_chart(patient_test_info[key].right_eye) + '</div>';
In response to your comment, I don't know how the chart code you're using works, but if d3.select("#row") is supposed to be targeting the div you've created, then you have 3 problems:
1) You're calling the function before the div has actually been added to the DOM. You need to do your html_info += '<div class="row">...' and ....innerHTML += html_info; first, then call draw_chart() afterwards.
2) You're targetting the <div class="row"> with select("#row") - assuming standard syntax, # denotes an ID, not a class. You either need to make it id="row" or select(".row") (a dot denotes a class). However, if you're planning to be able to call this function multiple times to add multiple charts, you'll need them to have unique names, otherwise you'll have trouble specifying that you want to use the latest row. I suggest using the ID and adding your "key" to it, assuming that's valid.
3) Again, I'm not sure how the chart code works, but I'd guess that it's going to replace the contents of the targetted div, not append to it, which means you'll lose the title from your row. If that's the case, I'd suggest putting another div inside your row div and giving it the name instead so you can target it, e.g. '<div><h4>'+ i +'. Patient: '+ key +'</h4>Date of birth: '+info[0]+'<br> Occupation: '+info[1]+'<br> Date of Test: ' + info[2] + '<div id="chart-' + key + '"></div></div>'. Once you've added that to the innerHTML, you can then call draw_chart(patient_test_info[key].right_eye, key) and modify your draw_chart method to use the key for the name, e.g. d3.select("#chart-" + key).
Related
I'm using Jquery $.post to get string array from SQL based on selection from a drop-down that I'm then reading into an HTML table. Each time they change selection on drop down, it clears all but the header row from the table and reloads new values. That is working fine.
It is just a basic 3 row table; a unique identifier, a value and a count shown as string. Every record has all 3, so I'm just using for loop with counters to control start/end of rows. In my form it's header is defined as such:
<div class="col-md-10">
<table id="attEditTable" style="width:100%" cellpadding="0" cellspacing="0" border="1" class="row">
<tbody>
<tr style="background-color: #F0F8FF;">
<th></th>
<th>Attribute Value</th>
<th>Item Count</th>
</tr>
</tbody>
</table>
</div>
I'm now trying to change the 1st cell of each row to a radio button with the value set to the value I was displaying in that cell.
Currently when the view displayed it is showing [object Object] in the first cell of every row instead of a radio button.
Sorry I am a newb at this with no training on Java or MVC - so hoping just a simple syntax issue...
Trying this basic one returned syntax error on input:
<input type="radio" name="SelERow" value='+editValues[i]+' />
I've also tried (both had same result of [object Object]):
$("input:radio[name=\"SelERow\"][value="+editValues[i]+"]")
$('<input type="radio" id="ERow" name="SelERow" value='+editValues[i]+' />')
Per David's suggestions I've now also tried (both resulted in no data and no error):
'<input type="radio" name="SelERow" value='+editValues[i]+' />'
var tblCell = $('<td />'); // create an empty <td> node
if (x == 1 || (x - 1) % 3 == 0) {
var input = $('<input />', { type: 'radio', id: 'ERow', name: 'SelERow', value: editValues[i] });
tblCell.append(input); // append an <input> node to the <td> node
} else {
tblCell.text(editValues[i]); // or just set the text of the <td> node
}
With the 2nd one I also changed the line: tblRow = tblRow + ""; to instead be tblRow = tblRow + tblCell + "";
Current Script
<script>
$(function () {
$("#EditAttributeName").change(function () {
var selectedName = $(this).val();
// Delete all but first row of table
$("#attEditTable").find($("tr")).slice(1).remove();
var url2 = "EditDD2changed?selectedName=" + selectedName;
$.post(url2, function (editValues) {
var x = 0;
var tblRow = "<tr>";
for (var i=0; i < editValues.length; i++)
{
x++;
if (x == 1 || (x - 1) % 3 == 0) {
tblRow = tblRow + "<td>" + $('input:radio[name="SelERow"][value="' + editValues[i] + '"]');
}
else {
tblRow = tblRow + "<td>" + editValues[i] + "</td>";
}
if (x % 3 == 0)
{
tblRow = tblRow + "</tr>";
$("#attEditTable").append(tblRow);
tblRow = "<tr>";
}
}
})
});
});
</script>
Console is showing no error messages.
Looks like it's close. To start, there's an important difference in the two attempts. This is a jQuery selector syntax:
$('input:radio[name="SelERow"][value="' + editValues[i] + '"]')
So it's not creating an <input/>, but looking for an <input/>. Which isn't what you want in this case. Your other attempt uses the syntax for creating an element:
$('<input type="radio" id="ERow" name="SelERow" value=editValues[i] />')
Though an issue here (which may have just been a copy/paste error in posting the question? but for completeness and for future readers it may as well be addressed...) appears to be that the editValues[i] is just part of the string. You want to concatenate it into the string. There are a couple ways to do that. Either direct concatenation:
$('<input type="radio" id="ERow" name="SelERow" value="' + editValues[i] + '" />')
Or string interpolation (take note of the different overall quotes, using back-ticks this time):
$(`<input type="radio" id="ERow" name="SelERow" value="${editValues[i]}" />`)
The latter is newer syntax but should be widely enough supported by now. (Though in any given business environment who knows what ancient browsers one may need to support.) Could just be personal preference between the two.
it is showing [object Object]
The main issue producing the result you've observing is that you're concatenating the result of that jQuery operation directly as a string:
tblRow + "<td>" + $('<input type="radio" id="ERow" name="SelERow" value="' + editValues[i] + '" />')
(Coincidentally, whether you're creating an element or looking for an element, this observed output would be the same because both operations return an object.)
The result of an $() operation is not itself a string, but a more complex object. When concatenated with a string it has to be interpreted as a string, and unless the object has a meaningful .toString() implementation (this one doesn't appear to) then the default string representation of a complex object is exactly that: "[object Object]"
There are a couple approaches you can take here. One would be to just use strings entirely, you don't necessarily need a jQuery object here:
tblRow + '<td><input type="radio" id="ERow" name="SelERow" value="' + editValues[i] + '" /></td>'
Since you're using jQuery later to append the result to the HTML, you can just build up all the HTML you like as plain strings and let jQuery handle turning them into DOM objects when you send them to .append().
The other option, if you definitely want to "use jQuery" in this situation or are otherwise being instructed to, would be to build the hierarchy of HTML elements as jQuery objects and then pass that hierarchy to .append(). Constructing such a hierarchy can look something like this:
var tblCell = $('<td />'); // create an empty <td> node
if (x == 1 || (x - 1) % 3 == 0) {
var input = $('<input />', { type: 'radio', id: 'ERow', name: 'SelERow', value: editValues[i] });
tblCell.append(input); // append an <input> node to the <td> node
} else {
tblCell.text(editValues[i]); // or just set the text of the <td> node
}
Note that each $() operation creates an HTML element node, and you can supply attributes for it as a second argument to the $() function. Then those nodes can be .append()-ed to each other just like you .append() the HTML string to $("#attEditTable").
In your particular case this may get a little more cumbersome because your loop isn't just looping through cells or just through rows, but through both and using a hard-coded count to determine whether it's reached the end of a row or not. So, as part of learning/practicing jQuery, it may be worth the effort to try this approach. But I suspect the shortest path to getting your code working with minimal changes would be the string concatenation approach above.
Side note: This code is using the same id value for the radio buttons created within this loop. The result is that there is expected to be multiple elements on the page with the same id. This is technically invalid HTML. If you ever try to use that id to reference an element, the resulting behavior will be undefined. (It might work in some cases, might not in others, purely coincidentally.) Though if you don't need to use that id to reference the elements, you may as well remove it entirely.
I document.write("<option></option>") 500 options for select in a function named laborlist(). When user click on select it just print out all those 500plus s on page nothing else. I don't know how to call javascript or php function in newTextBoxDiv.after().html
newTextBoxDiv.after().html('<select class="select2_single form-control" name="jobrequest' + counter + '"><option></option>' + laborlist() + '</select>');
Another question is which method is faster to make database table of 500 laborlist and call it through AJAX or method i am using? Thank you
function laborlist(){
var labourList = document.getElementById("labourList");
// use innerHTML instead of document.write()
labourList.innerHTML +="<option>1</option><option>2</option><option>3</option>and so on";
}
I don't think that would be possible.
Instead you can have a id for the select tag and use that id in laborlist() funtion to append option to it.
So it would be something like this:
newTextBoxDiv.after().html('<select id="labourList" class="select2_single form-control" name="jobrequest' + counter + '"><option></option>' + '</select>');
function laborlist(){
var labourList = document.getElementById("laborList");
// use innerHTML instead of document.write()
labourList.innerHTML += "<option>...</option>"
}
Our application is been internationalized and being changed to different languages. For that reason we have to hard code all the messages. How can we do that for messages in javascript ?
This is how we are doing in html messages.
<span th:text="#{listTable.deletedFromTable}">deleted</span>
How do we hard code for javascript messages.(update the table)
$('#TableUpdate-notification').html('<div class="alert"><p>Update the Table.</p></div>');
You will need to put the messages in the DOM from the start, but without displaying them. Put these texts in span tags each with a unique id and the th:text attribute -- you could add them at the end of your document:
<span id="alertUpdateTable" th:text="#{listTable.updateTable}"
style="display:none">Update the Table.</span>
This will ensure that your internationalisation module will do its magic also on this element, and the text will be translated, even though it is not displayed.
Then at the moment you want to use that alert, get that hidden text and inject it where you need it:
$('#TableUpdate-notification').html(
'<div class="alert"><p>' + $('#alertUpdateTable').html() + '</p></div>');
You asked for another variant of this, where you currently have:
$successSpan.html(tableItemCount + " item was deleted from the table.", 2000);
You would then add this content again as a non-displayed span with a placeholder for the count:
<span id="alertTableItemDeleted" th:text="#{listTable.itemDeleted}"
style="display:none">{1} item(s) were deleted from the table.</span>
You should make sure that your translations also use the placeholder.
Then use it as follows, replacing the placeholder at run-time:
$successSpan.html($('#alertTableItemDeleted').html().replace('{1}', tableItemCount));
You could make a function to deal with the replacement of such placeholders:
function getMsg(id) {
var txt = $('#' + id).html();
for (var i = 1; i < arguments.length; i++) {
txt = txt.replace('{' + i + '}', arguments[i]);
}
return txt;
}
And then the two examples would be written as follows:
$('#TableUpdate-notification').html(
'<div class="alert"><p>' + getMsg('alertUpdateTable') + '</p></div>');
$successSpan.html(getMsg('alertTableItemDeleted', tableItemCount));
I am trying to generate an HTML templaye from AngularJS directive but I'm not able to pass any object into a function within one of the generated elements. This is my directive:
app.directive('listObject', function($compile){
return {
scope : {
obj : "="
},
controller: "httpPostController",
link : function(scope, element) {
scope.elementTree = null;
//recursivly generate the object output
scope.printObject = function (field, content) {
if (field){
content = "<div>"
if (field.isRequired){
content += "<p>" + field.name + "*:</p>";
} else {
content += "<p>" + field.name + ":</p>";
}
if (field.isEnum){
content += '<select ng-model="createEntityResource[field.name]" ng-change="getCreateEntityAsText()" class="form-control">' +
'<option></option>' +
'<option ng-repeat="enumValue in field.enumValues" label={{enumValue.name}}>{{enumValue.ordinal}}</option>' +
'</select>';
} else if (field.restResourceName) {
content += '<button type="button" ng-click="loadResourceFieldsForField(field)">Create new</button>';
// content += "<p>"+i+""+scope.printObject(field)+"</p>";
} else {
content += '<input type="text" ng-model="createEntityResource[' + field.name + ']" ng-change="getCreateEntityAsText()"' +
'class="form-control" placeholder="{{parseClassName(field.type)}}">';
}
content+="</div>";
return content;
}
};
scope.refresh = function (){
if(scope.elementTree){
scope.elementTree.remove();
}
//generate the html into a string
var content = scope.printObject(scope.obj, content);
//make elements out of a string
scope.elementTree = angular.element(content);
compiled = $compile(scope.elementTree);
element.append(scope.elementTree);
compiled(scope);
};
scope.refresh();
}
};
});
When I create a <button> element - I give it a ng-click function. The function is called and works fine, except that the param it is passed (field) is always undefined.
Does anyone know how to pass object into function within an AngularJS directive?
Every useful answer is highly appreciated and evaluated.
Thank you.
P.S. I tried to split the definition of the button to :
'<button type="button" ng-click="loadResourceFieldsForField(' + field + ')">Create new</button>';
but this does not seem work, AngularJS argues about [Object object] being passed to a function.
P.P.S I also tried to make it according to documentation which says:
Often it's desirable to pass data from the isolated scope via an
expression and to the parent scope, this can be done by passing a map
of local variable names and values into the expression wrapper fn. For
example, if the expression is increment(amount) then we can specify
Blockquote
the amount value by calling the localFn as localFn({amount: 22}).
So it looks like this, but field is still undefined:
'<button type="button" ng-click="loadResourceFieldsForField({field: field})">Create new</button>';
So my printObject algorithm worked great :)
`<button type="button" ng-click="loadResourceFieldsForField(' + field + ')">Create new</button>`
The problem here is: You are generating a string.
And you print your object into the string. This will call toString within the object and won't do what you want to do. It will just print "loadResourceFieldsForField([Object])"
`<button type="button" ng-click="loadResourceFieldsForField({field: field})">Create new</button>`
The field property in the string doesn't have any reference to your param field in the method.
Within $compile: angularjs will search for a variable field within the scope and won't find any.
You have to place this field in the scope, to make this work as aspected. But it seems not like a easy job there.
I would try this:
$compile in each printObject with an own $scope.$new containing the field variable.
I have seen a similar question, HERE and have tried that, but I can't seem to get it working.
Here is my code for dynamically generating table rows.
for (var contribution = 0; contribution < candidate.contributions.length - 1; contribution++) {
var id = candidate.contributions[contribution].donor_id;
var uid = candidate.contributions[contribution].user_id;
$("#history-table").append(
"<tr onclick='" + parent.viewEngine.pageChange('public-profile', 1, id, uid) + ";>" +
"<td class='img-cell'>" +
"<img class='profile-avatar-small' src='/uploads/profile-pictures/" +
candidate.contributions[contribution].image + "' alt='' /></td><td class=''>" +
"<h2>" + candidate.contributions[contribution].firstname +
" " + candidate.contributions[contribution].lastname + "</h2></a><br/><br/>" +
"<span class='contribution-description'>" + candidate.contributions[contribution].contribution_description + "</span></td>" +
"<td><h3>$" + formatCurrency(candidate.contributions[contribution].contribution_amount) + "</h3></td></tr>");
}
This still executes the click event as soon as the page loads, which is not the desired behavior. I need to be able to click the tr to execute the click event.
Pass the whole thing as a string:
"<tr onclick='parent.viewEngine.pageChange(\'public-profile\', 1, " + id + ", " + uid + ");>" // + (...)
But, as you are using jQuery, you should be attaching the click handler with .on().
(I really don't recommend using inline event handlers like that, especially when you're already using jQuery, but anyway...)
The problem is that you need the name of the function to end up in the string that you are passing to .append(), but you are simply calling the function and appending the result. Try this:
...
"<tr onclick='parent.viewEngine.pageChange(\"public-profile\", 1, " + id + "," + uid + ");'>" +
...
This creates a string that includes the name of the function and the first couple of parameters, but then adds the values of the id and uid variables from the current loop iteration such that the full string includes the appropriately formatted function name and parameters.
Note that the quotation marks around "public-profile" were single quotes but that wouldn't work because you've also used single quotes for your onclick='...', so you should use double-quotes but they need to be escaped because the entire string is in double-quotes.
I'm wondering if you might be better simplifying things a bit.
If your rows are being dynamically added, then try putting some kind of meta-data in the <tr> tag, e.g. something like this:
<tr id="id" name="uid">
Then try the following with your jQuery (v.1.7 required):
$('#history-table tr').on('click', function(){
parent.viewEngine.pageChange('public-profile', 1, this.id, this.name);
});
This will likely require modification depending on how your page rendering works but it's a lot cleaner and easier to read having been removed from your main table markup.
Well that's because you're executing the function, not concatenating it. Try:
onclick='parent.viewEngine.pageChange("public-profile", 1, id, uid);'
Take this ->
$("#contribution-" + uid).click(function(){
parent.viewEngine.pageChange('public-profile',1, id, uid);
});
And do two things:
1) Move it outside of the 'for' statement
As soon as the for statement is executed, the click function will be executed as well. The click function is not being supplied as a callback function in this for statement.
2) Change it to ->
$("tr[id^='contribution-'").on('click', function(){
var idString = $(this).attr("id").split("-"); //split the ID string on every hyphen
var uid = idString[1]; //our UID sits on the otherside of the hyphen, so we use [1] to selec it
//our UID will now be what we need. we also apply our click function to every anchor element that has an id beginning with 'contribution-'. should do the trick.
parent.viewEngine.pageChange('public-profile',1, id, uid);
});
This is my solution.