Rendering jsx:element for semantic-ui dropdown - c#

I am new to using react.js, using a C# API, and trying to use the semantic-UI dropdown that allows HTML in the content of the dropdown items.
I'm having trouble returning the "content" field below. It looks like a jsx:element type, not a string or number like the other types.
I can hardcode it, but I can't return it from the API.
Here is the example from the Semantic documentation which seems like an invalid JSON to me. For now, I've given up on this, but still curious how JSON like this is supposed to be returned from c# .net core API.
const options = [
{
key: 1,
text: 'Mobile',
value: 1,
content: (
<Header icon='mobile' content='Mobile' subheader='The smallest size' />
),
},
{
key: 2,
text: 'Tablet',
value: 2,
content: (
<Header
icon='tablet'
content='Tablet'
subheader='The size in the middle'
/>
),
},
{
key: 3,
text: 'Desktop',
value: 3,
content: (
<Header icon='desktop' content='Desktop' subheader='The largest size' />
),
},
]
This is my the code in the API that currently sends the dropdown items:
[HttpGet(Name = "GetCaseDropdown")]
public IEnumerable<CaseDropdownItem> Get()
{
var db = new CaseDBContext();
var records = (from x in db.Cases
select new CaseDropdownItem()
{
content = "<b>"+ x.StrCnCasenum + "</b>" + " " + x.StrCnName, // Does not render within parentheses which is required
text = x.StrCnName,
value = x.StrCnCasenum,
key = x.StrCnCasenum
}).ToArray();
return records;
}
And the react code that fetches the data:
fetch("casedropdown")
.then((response) => response.json())
.then((data) =>
setCaseOptions(
data.map((x) => {
return { key: x.key, text: x.text, value: x.value, content: x.content };
})
)
);

Related

getting JSON string into Knockout observable multiselectlist

I am trying to get my JSON string passed through the ViewBag into my knockout observable and use that to populate a multiselectlist. I'm not sure what I am doing wrong, but right now it is taking each individual character in the JSON string and sticking it in it's own line in the select list.
Here is my C# controller code:
Dictionary<string, string> salesReps = new Dictionary<string, string>();
foreach ( var rep in salespeople.Salesperson )
{
salesReps.Add( rep.Code, rep.Code + " - " + rep.fullName );
}
//ViewBag.salespeople = salespeople.Salesperson.Select( x => x.Code ).Distinct().ToList();
ViewBag.salespeople = JsonConvert.SerializeObject( salesReps );
And here is the Knockout code:
var cSource = function (data) {
var self = this;
.....
self.salesPeople = ko.observableArray();
};
$(document).ready(function () {
var modelData = #Html.Raw( Json.Encode( Model ) );
mySource = new cSource(modelData);
//var salesRepList = Html.Raw( Json.Encode( ViewBag.salespeople ) );
var salesRepList = #Html.Raw(Newtonsoft.Json.JsonConvert.SerializeObject(ViewBag.salespeople));
console.log(salesRepList);
mySource.salesPeople = salesRepList;
And here is the HTML select code:
<select data-bind="
options: salesPeople,
selectedOptions: chosenReps,
optionsCaption: 'Choose rep(s)'
"></select>
And a small snippet of what my console.log spits out:
{"USERNAME1":"USERNAME1 - Full Name 1","USERNAME2":"USERNAME2 - Full Name 2","USERNAME3":"USERNAME3 - Full Name 3",..... }
UPDATE
I changed the c# code to create named variables in the JSON now. Here is my new console.log output:
{"username":"BOBC","fullname":"Bob Cottin"},{"username":"JIMT","fullname":"Jim Thorpe"},{"username":"LUKEP","fullname":"Luke Peppin"}, ....}
The options binding is expecting an array of objects or values, but according to your console log salesPeople is a single dictionary style object. You may need to convert that to an array so the binding knows how to parse it into select options.
If you only need the value property and can disregard the "Username1", "Username2", etc then you could use a loop like this to grab the value properties of the object:
for (var x in salesRepList) {
if (salesRepList.hasOwnProperty(x)) {
mySource.salesPeople.push(salesRepList[x]);
}
}
If you need the more complex types then you'll have to create an array of objects, or (per your last edit) have your json pass them with standard parameter names. Then you can use knockout's optionsText binding to tell the select which property on the object to use as the display text.
Per example:3 of the knockout docs
<select data-bind="options: availableCountries,
optionsText: 'countryName',
value: selectedCountry,
optionsCaption: 'Choose...'"></select>
Here's a jsFiddle with some of that adapted to your example: fiddle

push items in array of array in jQuery

I am a beginner in using jQuery Float Chart. Now I try to bind the chat with server side values. I need to build an array structure like below.
data = [{
label: 'Test 1',
data: [
[1325376000000, 1200],
[1328054400000, 700],
[1330560000000, 1000],
[1333238400000, 600],
[1335830400000, 350]
]
},];
My Server Response
My question is how to push items in this array of array. I already try to build an array like this:
var data = new Array();
var chartOptions;
$.each(graphdata, function (key, value) {
data.push({
label: value.label,
data: $.each(value.data, function (key, value) {
Array(value.X, value.Y);
})
})
});
Edits
Graph shows in webpage
But it's not working.
The problems is that $.each return collection that iterates on - the collection you don't want to.
You can use underscore library that contains function map to project value into another:
var postData = [{label:"test1", "data": [ {X: "10", Y:"11"}, {X: "12", Y: "13"}] }];
var data = []
$.each(postData, function (key, value) {
data.push({
label: value.label,
data: _(value.data).map(function(innerVal) {
var arr = new Array();
arr.push(innerVal.X);
arr.push(innerVal.Y);
return arr;
})
})
});
Here is jsFiddle: click!

Pass array as query string in jquery

I have created one string array in jquery of name array[] and pushed values to it.
How can I send this array in query string?
For example window.location.href('ViewData?array');
And how can I get back the array data from query string in jquery itself ?
Please advice?
This is very easy to achieve with jQuery as it has a helper function called param().
var myData = {
name: "John Doe",
age: 23,
children: [{
name: "Jane Doe",
age: 13,
children: []
},
{
name: "John Doe Jr.",
age: 16,
children: []
}
],
}
var p = $.param(myData)
The results:
"name=John+Doe&age=23&children%5B0%5D%5Bname%5D=Jane+Doe&children%5B0%5D%5Bage%5D=13&children%5B1%5D%5Bname%5D=John+Doe+Jr.&children%5B1%5D%5Bage%5D=16"
You can use it like so:
window.location = "/MyController/MyAction?" + p;
As for getting parameters from query strings, please refer to the following question: How can I get query string values in JavaScript?
Another thing you can do is use an ajax call, this way you don't have to serialize the data yourself as it is done for you automatically.
$.ajax({
url: "/MyController/MyAction",
data: myData,
dataType: "json",
type: "POST",
success: function(data){
//'data' is your response data from the Action in form of a javascript object
}
})
I think this is what you are looking for. Let me know if I get it wrong. I copied $.parseParams from this link. You can also see working code here
(function($) {
var re = /([^&=]+)=?([^&]*)/g;
var decodeRE = /\+/g; // Regex for replacing addition symbol with a space
var decode = function (str) {return decodeURIComponent( str.replace(decodeRE, " ") );};
$.parseParams = function(query) {
var params = {}, e;
while ( e = re.exec(query) ) {
var k = decode( e[1] ), v = decode( e[2] );
if (k.substring(k.length - 2) === '[]') {
k = k.substring(0, k.length - 2);
(params[k] || (params[k] = [])).push(v);
}
else params[k] = v;
}
return params;
};
})(jQuery);
var s=["abc", "xyz", "123"];
var queryString=$.param({a:s});
console.log("object to query string: ", queryString);
console.log("query string to object: ", $.parseParams(queryString));

Merging Razor with Jquery for autocomplete function

im using this guide http://jqueryui.com/autocomplete/#custom-data and what little i know of C# and razor to try autocomplete 3 textboxes whenever one of them is picked.
so if i type in the partno and choose one from the drop down list, item name, desc and ID are populated. and the same if i type in any other field.
i have created a class and put it in a list with the items in
var varItems = new List<Item>();
varItems = db.Items.Select(tbl => new Item
{
ID = tbl.ID,
Name = tbl.Name,
PartNo = tbl.PartNo,
Description = tbl.Description
}).ToList();
then sent that in a viewbag
ViewBag.Items = var.items;
then in the view
$( "#Name" ).autocomplete({
minLength: 0,
source: #ViewBag.Items,
focus: function( event, ui ) {
$( "#Name" ).val( ui.item.label );
return false;
},
select: function( event, ui ) {
$( "#Name" ).val( ui.item.Name );
$( "#PartNo" ).val( ui.item.PartNo );
$( "#Description" ).html( ui.item.Description );
return false;
}
});
but it doesnt like the viewbag being there. im guessing i have to do some sort of loop to produce something like the below?
var projects = [
{
value: "jquery",
label: "jQuery",
desc: "the write less, do more, JavaScript library",
icon: "jquery_32x32.png"
},
{
value: "jquery-ui",
label: "jQuery UI",
desc: "the official user interface library for jQuery",
icon: "jqueryui_32x32.png"
},
{
value: "sizzlejs",
label: "Sizzle JS",
desc: "a pure-JavaScript CSS selector engine",
icon: "sizzlejs_32x32.png"
}
];
if so how do i loop my list to create the above?
Thanks guys
try this:
source: #Html.Raw(Json.Encode(#ViewBag.Items));
This would encode your Items to json and it should work.

Controlling Group order in a Kendo UI Grid

Is there a way to control the order of the grouping in a Kendo UI grid. There is a group I would like to go before all other groups, but it seems Kendo UI grid sorts the groups alphabetically. I know that adding a space to the grouping name works but that's seems very hackish.
Thanks
Leo
There is currently no way to sort a grouping on something other than the group's field. Having a way to sort groups like Telerik does in their non-Kendo grids is my biggest feature request for them right now. So we are stuck using hacks for now.
One hack that works for me is to combine the sorting field and the display field into a new string column that hides the sorting field portion inside a hidden span. This is done on the data source side (for me, in SQL). The new column is then sorted as a string even if the sorting field was a number, so you have to pad appropriately in some cases.
For example, if my data was:
[
{
'Name': 'Alice',
'Rank': 10,
'RankName': '<span class="myHiddenClass">10</span>Alice',
... (other fields)
},
{
'Name': 'Bob',
'Rank': 9,
'RankName': '<span class="myHiddenClass">09</span>Bob',
... (other fields)
},
{
'Name': 'Eve',
'Rank': 11,
'RankName': '<span class="myHiddenClass">11</span>Eve',
... (other fields)
}
... (Multiple Alice / Bob / Eve records)
]
Then I can group by the RankName field instead of the Name field. It will display the Name field in the group header but be sorted by the Rank field. In this case, Bob will show up as the first group even though Alice was first alphabetically. This works similarly to the space padding you mentioned.
Try AddDescending and AddAscending, see examples below
#(Html.Kendo().Chart<T>()
[... other code ...]
.DataSource(ds => ds
.Read(read => read.Action("action", "controller"))
.Group(g => g.AddDescending(model=> model.property)) // <-- subtle difference here!
)
[... other code ...]
)
http://www.telerik.com/forums/stacked-chart-legend-order
Kendo's grouping sorts all elements in the array by a given field (for example fooBar), then iterates the sorted elements. In a nutshell, with pseudo code:
if (element[i].fooBar!= element[i-1].fooBar) {
StartNewGroup(element[i]);
} else {
AddToLastGroup(element[i]);
}
Since the sorted array is required to do the grouping, it is tricky to change the sorting. I created code to override the internal groupBy() function, which allows me to sort the grouped results however I like:
function overrideKendoGroupBy() {
var origFunc = kendo.data.Query.prototype.groupBy;
kendo.data.Query.prototype.groupBy = function (descriptor) {
var q = origFunc.call(this, descriptor);
var data = SortYourData(q.data, descriptor.dir);
return new kendo.data.Query(data);
};
}
Call overrideKendoGroupBy() at some point after your page loads. Now just implement a SortYourData() function where q.data is an array of groupings, and descriptor.dir is "asc" or "desc". q.data[n] has an items array that contains the elements from your original data source that are contained in the nth grouping.
Note: This solution only works if you aren't using paging. The pages are broken up before grouping is applied, so all bets are off if your data spans multiple pages.
The below code will push the group that fulfils the if condition to bottom of the grid
group: {
dir: "asc",
field: "FieldToGroupBy",
compare: function (a, b) {
if (b.value == "GROUP_TO_SHOW_LAST") {
return -1; // this will push the group to bottom
}
}
},
If you want to compare groups with each other, you should use a and b and then set the return value accordingly.
You need to play around with the return value based on your requirement.
Note: return value should be any of 0, 1, -1
Custom sorting direction when grouping is not supported by the Grid - the groups are sorted the same way as the column is sorted (when using client sorting) when there is not grouping. The sorting direction is the same as the default sort in JavaScript.
You can add a query after you have defined the datasource and this seems to work
related.query({
sort: { field: "Sort", dir: "asc"},
group: { field: "CategoryName" },
pageSize: 50
});
Where related is the name of the datasource
An old question but I just had the same issue
In theory you can follow the advice here: https://github.com/telerik/kendo-ui-core/issues/4024
$("#grid").kendoGrid({
...
groupable: {
sort: {
dir: "asc",
compare: function compareByTotal(a, b) {
if (a.items.length === b.items.length) {
return 0;
} else if (a.items.length > b.items.length) {
return 1;
} else {
return -1;
}
}
}
}
}
However this didn't work for me.
What did work for me was...
Add an extra column to your dataSource, so now you have
GroupByName
GroupByOrder
In your schema do
dataSource = {
data: dataProperties,
schema: {
model: {
fields: {
groupByName: {
type: "string",
from: "dataPropertyDefinition.GroupName"
},
groupOrderBy: {
type: "string",
from: "dataPropertyDefinition.groupOrderBy"
}
}
}
},
group: {
field: "groupOrderBy",
}
};
So now you are ordering by groupOrderBy, which can be whatever you like, and you use the groupHeaderTemplate to show the name instead
const columns: Array<object> = [
{
field: "groupOrderBy",
hidden: true,
groupHeaderTemplate: function (x: any)
{
return x.items[0].groupByName;
}
}
Here is a simple workaround for this. Not pretty but simple enough...
Just add spaces in front of the text to achieve desirable sorting
[{
'Value': 1,
'Description': 'Description 1',
'Grouping': 'Group 1'
},
{
'Value': 2,
'Description': 'Description 2',
'Grouping': ' Group 2'
},
{
'Value': 3,
'Description': 'Description 3',
'Grouping': 'Group 3'
}]
In the sample code above Group 2 appears before Group 1 because of a leading space.
Use columns to specify the order of columns once you have your data such as
columns: [
{
field: "LastName",
title: "Last Name"
},
{
field: "FirstName",
title: "First Name"
}
]

Categories

Resources