Angular how to compile whole jTable after dynamic load from server - javascript

I am using .NET to assemble some of the fields on the server for jTable. My problem is how to compile changed table after load, so angular events are compiled to $scope. What I've tried is to compile the whole html body, but it doesn't work. Nothing happens. What should I do? Some fields must be assembled on the server. Why is $compile($("body"))($scope) not compiling whole body?
My thinking is that whatever element is added to DOM, if I compile the whole documents body, all angular events should be binded to $scope.
Here is the function on the server (ng-blur event is added to the input field inputQuantity):
public JsonResult GetListFromIACC_KEY(int jtStartIndex, int jtPageSize, string orderBy)
{
List<DTO_CAMERC> listResults = new List<DTO_CAMERC>();
x.Quantity = SetTextBoxFieldInJTable(value: x.Quantity,
attribute1: #"id='inputQuantity'",
attribute2: #"ng-blur='alert();'");
return x;
}).OrderBy(x => x.iMERC_KEY).ToList();
}
return Json(new { Result = "OK", Records = listResults, TotalRecordCount = listResults.Count });
}
Function for creating input field:
private string SetTextBoxFieldInJTable(string value = null, string attribute1 = null, string attribute2 = null)
{
return #"<input type='text' class='cellContent'" +
"value='" + value + #"' " + attribute1 + " " +
attribute2 + ">";
}
Client call (here I've tried to compile whole html body after jTable has loaded, but id doesn't work - nothing happens when field inputQuantity loses focus):
$http({
method: "POST",
url: $scope.UrlSetIACCO_KEY,
data: JSON.stringify(model)
}).then(function success(response) {
jQuery('#tblDeliveryList').jtable('load');
//Here I try to compile the whole body, after the jTable has loaded,
//but ng-blur is not working
$compile($("body"))($scope);
}, function failure() {
alert("Napaka!");
})
});
Table on the client:
jQuery('#tblDeliveryList').jtable({
title: 'Delivery',
paging: true,
pageSize: 10,
sorting: true,
defaultSorting: 'cMERC_NME ASC',
actions: {
listAction: $scope.UrlGetDataFromIACCO_KEY
},
Quantity: {
title: 'Quantity',
width: '3%',
sorting: false
}
})

You are doing the compile wrong. $('body') returns a jQuery object. What you need to do is to return HTML dom object for angular to compile. Also, compiling the jTable html alone is enough. Try the following:
$compile(document.getElementById('tblDeliveryList'))($scope);

Related

Using ajax call to generate array for link_list for tinymce

I'm trying to create a link_list in TinyMCE (version 6) using an AJAX call (not sure if this is the right way, but I'm trying to update old code). The backend is handled with Flask, which gets a tuple of dictionaries from the database where the title and value of each link are key-value pairs. I believe what I need to do is find a way to make the ajax call return the correct type of array, e.g.
my_ary=[
{ title: 'title 1',value: 'link1'},
{ title: 'title 2',value: 'link2'},
{ title: 'title 3',value: 'link3'},
]
Is this possible? Or am I heading in a completely incorrect direction? This is what I currently have-
tinyMCE intialization:
tinymce.init({
selector: '.my_editor',
plugins: ['link'],
toolbar: 'link',
link_list: (success) => {
const links = update_item_list();
success(links);
},
});
javascript containing ajax call:
function update_item_list()
{
my_link_list = $.ajax({
async: false,
type: "POST",
url: "ajax_endpoint",
data: {},
cache: false,
dataType: "json",
success: function(list)
{
const my_ary=Array.from(Array(list.length), () => ({ title: '', value: '' }))
for(var i = 0; i < list.length; i++)
{
my_ary[i].title=list[i].title;
my_ary[i].value=list[i].value;
}
},
error: function(html, status)
{
alert("error: " + status);
}
});
return my_link_list;
}
flask endpoint:
#my_project.route('/ajax_endpoint',methods=['POST'])
def ajax_endpoint():
uploaded_items = ["{" + ", ".join([f"""'{key}': '{item.get(key)}'""" for key in item.keys()]) + "}" for item in get_link_items()]
html = "[" + ", ".join(uploaded_items) + "]"
return jsonify(html)
I figured out a solution without using ajax. Per tinyMCE's documentation for link_list, one can use a URL which returns JSON data. To accomplish this, I created a list of dictionaries with keys of "title" and "value" for each link, and then used jsonify when returning the list. Now, this is what my code looks like-
tinyMCE intialization:
tinymce.init({
selector: '.my_editor',
plugins: ['link'],
toolbar: 'link',
link_list: "ajax_endpoint"
},
});
flask endpoint:
#my_project.route('/ajax_endpoint',methods=['POST'])
def ajax_endpoint():
html = [{"title": item.get('title'), "value": item.get('value')} for item in get_link_items()]
return jsonify(html)

How to get a value of a function from a javascript file to an ASP.NET MVC view?

i am trying to separate my view from java script,in my view im calling a function in js file to create a chart,
Here is my js file and the function:
function pieChartForInterventions(chartID,pieChartData) {
chartID.kendoChart({
dataSource: {
data: pieChartData
},
series: [{
type: "pie",
field: "list",
categoryField: "mm",
padding: 0,
labels: {
visible: true,
}
}],
seriesClick:onDb,
tooltip: {
visible: true,
template: "${ category }"
}
,
legend: {
position: "bottom"
}
});
}
function onDb(e) {
var _clicked = e.category;
}
here is my view:
pieChartForInterventions($("#pieChart"), result);
now the problem is,as you see in my function i have a onDb() function whick invokes when i click on my chart to get the value of what i clicked,i need this value to send it back with a Ajax call via my view,how should i have this value in my view?
Please elaborate a bit more, where exactly in your view do you require this value? OR what do you want to do with this value after receiving it in the view?
If you have something available in javascript, it means you already have it in your “View”, since the only place your javascript logic is executing is in your view.
From your onDb(e) function, you can:
1) Return the value and use it anywhere you need within the view via javascript logic.
In your sepearated js file you may have a function like:
function onDb(e) {
var _clicked = e.category;
return _clicked;
}
Somewhere in your view (.cshtml) you may do something like:
<script type="text/javascript">
// Get 'e' from wherever you need
var requiredValue = onDb(e);
// Any Javascript / JQuery / Ajax logic ...
</script>
2) If the returned value is required at the server side, you can send an AJAX request etc. See the following on how to send an AJAX request (MVC jquery ajax call with input parameter)
==== UPDATE AFTER COMMENT ====
You can access the onDb function the same way as I mentioned in the second code snippet. However, in that case getting the input parameter “e” would require some scripting.
Alternatively, what’s even easier in this scenario is that you can move the “Ajax Call” inside onDb(e) function. Update the onDb(e) function as follows …
function onDb(e) {
var _clicked = e.category;
$.ajax({
type: "POST",
url: '#Url.Action("ControllerName", "ActionName")',
contentType: "application/json; charset=utf-8",
data: { valueToSend: _clicked },
dataType: "json"
});
}
And on your server side you would have some action like:
public class ControllerName : Controller
{
[HttpPost]
public ActionResult ActionName(string valueToSend)
{
//The value you needed is stored in the input paramater 'valueToSend'
//... process however you want and return any ActionResult ...
return Json("success", JsonRequestBehavior.AllowGet);
}
}

Kendo UI Grid Javascript datasource call to controller action

I'm having trouble binding my JavaScript kendo ui grid to model data from an action method. All the examples i see are mostly MVC wrappers and the JavaScript examples are all different and none seem to work for me.
Here is where i'm at below.
I did a generic test with static data that works.
var dataSource_Test = new kendo.data.DataSource({
data: [{ LeagueDetailGroupId: "15", GroupName: "Best Team 5"}]
});
Here is the datasource object im trying to create with the controller action:
var dataSource = new kendo.data.DataSource({
transport: {
read: {
url: "#Url.Action("LeagueDetailGroup_Read", "Configuration")?_leagueTypeId=" + leagueTypeId,
// i have tried all kinds of variants here, and not sure what to put
// my action method is returning json using kendo's DataSourceResult method
//contentType: "application/json",
type: "POST"
//dataType: "odata"
},
schema: {
data: "Data", // seen this in examples, dunno what it does
total: "Total", // seen this in examples, dunno what it does
model: {
id: "LeagueDetailGroupId",
fields: {
LeagueDetailGroupId: { editable: false, nullable: true },
GroupName: { validation: { required: true } }
}
}
},
// i seen this is an example from telerik but dont understand the use case for it
parameterMap: function (data, operation) {
// this prints no data before i even start so its a moot point configuring it from products to my stuff at this moment
// but not sure what todo here of if i need this anyways
console.log(data);
if (operation != "read") {
// post the products so the ASP.NET DefaultModelBinder will understand them
var result = {};
for (var i = 0; i < data.models.length; i++) {
var product = data.models[i];
for (var member in product) {
result["products[" + i + "]." + member] = product[member];
}
}
return result;
} else {
return JSON.stringify(data)
}
}
}
});
Here is the grid which works ok with the generic static datasouce object.
var grid = $("#leagueEdit_ldg_grid").kendoGrid({
dataSource: dataSource,
sortable: true,
pageable: true,
autobind: false,
//detailInit: leagueEdit_ldg_detailInit,
dataBound: function () {
this.expandRow(this.tbody.find("tr.k-master-row").first());
},
columns: [
{
field: "LeagueDetailGroupId",
title: "Group Id",
width: "110px"
},
{
field: "GroupName",
title: "Group Name",
width: "110px"
}
]
});
Delayed read, autobind set to false.
dataSource.read();
Here is my simplified Controller action. It runs and gets data, and works fine for my MVC wrapper grids.
[Route("LeagueDetailGroup_Read/{_leagueTypeId:int}")]
public ActionResult LeagueDetailGroup_Read([DataSourceRequest]DataSourceRequest request, int _leagueTypeId = -1)
{
DataSourceResult result =
_unitOfWork.FSMDataRepositories.LeagueDetailGroupRepository.Get(
ld => ld.LeagueTypeId == _leagueTypeId
)
.ToDataSourceResult(request,
ld => new LeagueDetailGroupViewModel
{
LeagueDetailGroupId = ld.LeagueDetailGroupId,
LeagueTypeId = ld.LeagueTypeId,
GroupName = ld.GroupName,
DateCreated = ld.DateCreated,
DateLastChanged = ld.DateLastChanged
}
);
// data looks fine here
return Json(result, JsonRequestBehavior.AllowGet);
}
Currently i'm getting this error:
Uncaught TypeError: e.slice is not a function
at init.success (kendo.all.js:6704)
at success (kendo.all.js:6637)
at Object.n.success (kendo.all.js:5616)
at i (jquery-3.1.1.min.js:2)
at Object.fireWith [as resolveWith] (jquery-3.1.1.min.js:2)
at A (jquery-3.1.1.min.js:4)
at XMLHttpRequest.<anonymous> (jquery-3.1.1.min.js:4)
It's hard to know without testing but let me know how this works.
Change your controller so that you are just returning a json string.
Also, try removing your schema and the parameter map, and set your dataType to json:
var dataSource = new kendo.data.DataSource({
transport: {
read: {
url: "#Url.Action("LeagueDetailGroup_Read", "Configuration")?_leagueTypeId=" + leagueTypeId,
dataType: "json"
}
}
});
For the grid I find simple json data does not usually need a schema/model defined. Kendo is super annoying and hard to debug. Let me know how it goes.
In my experience, an e.slice error happens when you have a record that has a null value in it somewhere. The kendo grid is not really smart enough to deal with this so you either have to make sure your datasource returns empty strings instead of nulls for string fields, or put a client template on the columns that translates a null into an empty string. It's possible that the kendo todatasourceresult made the problem come to light. Note that that is usually the last step before returning your dataset since it can modify the entity queries to give paging, so that you never query more than a single page of data (for ajax grids).

Using Select 2 with ASP.NET MVC

I am working on an ASP.NET MVC 4 app. In my app, I'm trying to replace my drop down lists with the Select 2 plugin. Currently, I'm having problems loading data from my ASP.NET MVC controller. My controller looks like this:
public class MyController : System.Web.Http.ApiController
{
[ResponseType(typeof(IEnumerable<MyItem>))]
public IHttpActionResult Get(string startsWith)
{
IEnumerable<MyItem> results = MyItem.LoadAll();
List<MyItem> temp = results.ToList<MyItem>();
var filtered = temp.Where(r => r.Name.ToLower().StartsWith(startsWith.ToLower());
return Ok(filtered);
}
}
When I set a breakpoint in this code, I notice that startsWith does not have a value The fact that the breakpoint is being hit means (I think) my url property below is set correct. However, I'm not sure why startsWith is not set. I'm calling it from Select 2 using the following JavaScript:
function formatItem(item) {
console.log(item);
}
function formatSelectedItem(item) {
console.log(item);
}
$('#mySelect').select2({
placeholder: 'Search for an item',
minimumInputLength: 3,
ajax: {
url: '/api/my',
dataType: 'jsonp',
quietMillis: 150,
data: function (term, page) {
return {
startsWith: term
};
},
results: function (data, page) {
return { results: data };
}
},
formatResult: formatItem,
formatSelection: formatSelectedItem
});
When this code runs, the only thing I see in the select 2 drop down list is Loading failed. However, I know my api is getting called. I can see in fiddler that a 200 is coming back. I can even see the JSON results, which look like this:
[
{"Id":1,"TypeId":2,"Name":"Test", "CreatedOn":"2013-07-20T15:10:31.67","CreatedBy":1},{"Id":2,"TypeId":2,"Name":"Another Item","CreatedOn":"2013-07-21T16:10:31.67","CreatedBy":1}
]
I do not understand why this isn't working.
From the documentation:
Select2 provides some shortcuts that make it easy to access local data
stored in an array...
... such an array must have "id" and "text" keys.
Your json object does not contain "id" or "text" keys :) This should work though i have not tested it:
results: function (data, page) {
return { results: data, id: 'Id', text: 'Name' }
}
There's further documentation following the link on alternative key binding... I believe thats where your problem lies.
Hopefully this helps.

Convert string to Javascript object for use in jqTree

I'm trying to use jqTree to render a collapsible tree to display data from a MySQL database via an ASP.NET project using AJAX.
The Problem:
I can successfully get the string containing the jqTree formatted data (which is not JSON even though they say it supports it) back from my AJAX call. However, once I get it there it get rendered as a vertical string of characters. If I do a typeof call on the data, it says it's a string, even though it 'looks' like an object when visually inspected via console.log.
I have tried a number of different ways to get the string into an object, with varying results.
I'm using this in the code behind to return the manufactured string:
return sb.ToString();
The resultant string looks like this (notice no wrapping quotation marks):
[{label: 'PCBID: 350',children:[{label: 'TimeStamp: 04-Sep-14 10:30:23'},{label: 'User: DAVEG'},{label: 'PCBID: 350'},{label: 'Assembly Drawing: 41411'},{label: 'PCB Drawing: 10348'},{label: 'Vendor: SBE'},{label: 'PO Number: 98019'}]},{label: 'Serial Number: Not Assigned'},{label: 'Assembly Drawing: 41411'},{label: 'Last Test Result: None Found'}]
Which gets rendered like this in my div:
[
{
l
a
b
e
l
:
'
P
C
B
I
D
...and so on...
I know these are being rendered by jqTree because I can drag & drop them, they highlight when clicked on, etc., but instead of a tree view, I get a "dangling vine" view, not exactly useful.
If I simply take that same exact same string and declare it as a var inside the JS (not using the return value of message.d):
var data = [{label: 'PCBID: 350',children:[{label: 'TimeStamp: 04-Sep-14 10:30:23'},{label: 'User: DAVEG'},{label: 'PCBID: 350'},{label: 'Assembly Drawing: 41411'},{label: 'PCB Drawing: 10348'},{label: 'Vendor: SBE'},{label: 'PO Number: 98019'}]},{label: 'Serial Number: Not Assigned'},{label: 'Assembly Drawing: 41411'},{label: 'Last Test Result: None Found'}]
inside my JS code & use that, it displays perfectly and typeof thinks it's an object.
Working Example so you can see what I'm looking for:
JSFiddle
The Code on the JS side:
Here's the Success portion of my AJAX call with a bunch of commented out versions that don't work either:
success: function (message)
{
console.log("SUCCESS: Inside processEvent AJAX success call");
console.log(message.d);
console.log(typeof message);
console.log(typeof message.d);
var data = message.d;
//this method works, but not very useful as it's hard coded:
//var data = [{ label: 'PCBID: 350', children: [{ label: 'TimeStamp: 04-Sep-14 10:30:23' }, { label: 'User: DAVEG' }, { label: 'PCBID: 350' }, { label: 'Assembly Drawing: 41411' }, { label: 'PCB Drawing: 10348' }, { label: 'Vendor: SBE' }, { label: 'PO Number: 98019' }] }, { label: 'Serial Number: Not Assigned' }, { label: 'Assembly Drawing: 41411' }, { label: 'Last Test Result: None Found' }];
var data = $.getJSON(message.d);
//var data = { JSON.parse(message.d) };
//var data = ({}).valueOf.call($.parseJSON(message.d));
//var data = object.create(message.d);
console.log(typeof data);
console.log(data);
$(function ()
{
$('#tree1').tree({
data: data,
autoOpen: false,
saveState: true,
dragAndDrop: true
});
});
The Question:
So after all that, my question is, how do I take the string from the AJAX message.d and turn it into an object so that jqTree can use it to render the tree I'm looking for?
Working Code:
I've added back in some of the success user informing stuff (jGrowl) so don't let that throw you. The bit of code that fixed it is here: data = eval($.parseJSON(message.d));
success: function (message)
{
console.log("SUCCESS: Inside processEvent AJAX success call");
console.log(message.d);
//if it's a non query event, do this
if (DTO.eventData.eventType != "PCBID_query")
{
$.jGrowl("\nSuccessfully inserted a " + DTO.eventData.eventType + " event into the MySQL database.",
{ header: 'SUCCESS', theme: "pcb-success", life: 10000 });
}
//if processData was used for a PCBID query, process this code
if (DTO.eventData.eventType === "PCBID_query")
{
var data = {};
data = eval($.parseJSON(message.d));
$(function ()
{
//force reload of tree data
$('#tree1').tree('loadData', data);
$('#tree1').tree({
data: data,
autoOpen: false,
saveState: true,
dragAndDrop: true
});
});
}
I know the eval is evil & presents a security hole, however, this is all internal code that'll only be used on local servers & production floor computers so I think the risk is acceptable (as does my manager).
eval(data) would work in this case, but using eval() is usually a security issue, especially when getting data from public areas, such as user submitted SQL data.
The best solution would be to look for a real way to export JSON from your ASP.NET. Without knowing your code, a little googling shows there are solutions out there.

Categories

Resources