How to define an object variable like this in JQuery? - javascript

I would like to create a variable and populate data and make the output of the variable like the following pseudo code:
myObj = {
"Title":"Test",
"Paragraphs":
[
{
"Order":"1",
"Id": "2"
},
{
"Order":"2",
"Id": "1"
},
{
"Order":"3",
"Id": "2"
}
]
}
And use JQuery to POST to MVC controller action at the back end using a defined data model:
public class TemplateBuilderViewModel
{
public string Title { get; set; }
// Not sure if I should use Dictionary or something else
public Dictionary<int, int> Paragraphs { get; set; }
}
I am not sure how to declare the variable and populate data into the variable with the data structure I want in the output.
Any suggestions? Thank you.

This is what I get working in the end in JQuery.
Declare an array type, use push to insert values and assgin the arrary variable into the object type variable.
var dict = [];
for (i = 1; i < counter; i++) {
var paragraphId = Id;
var order = order;
dict.push({
"ParagraphId": paragraphId,
"ParagraphOrder": order
});
}
var templateBuilder = {
TemplateTitle: title,
ParagraphTitle: "",
ParagraphTitleList: undefined,
ParagraphText: "",
ParagraphOrder: dict
};

Related

Get all json key and value from an external json file in MVC with javascript

I am creating a web app in which I have a Json file in which I have many keys with values, like the following,
{
"Login_Header_Text": "Login",
"Login_Header_Recent_Updates": "Recent Updates",
"Login_TextBox_UserName": "User Name",
"Login_TextBox_Password": "Password",
"Login_Button_Login": "Log In",
"Login_ErrorMessage_Usernamerequired": "User name required",
"Login_ErrorMessage_Passwordrequired": "Password required.",
"Login_ErrorMessage_Invalid_Credentials": "Invalid user name/password",
}
and I can retrieve the values like the following
<script>
console.log('#HttpContext.GetGlobalResourceObject("", "Login_TextBox_UserName")');
</script>
now, how can I retrieve whole json file data and print that into my console,
Like, if I have 55 Records in the json file, whole data should be printed in console.log
what is the proper way to do this?
here is how i would do it. in C# and also in javascript
assum we have this js
var json = [{Name: "test", Passowrd:"test" }]
in C# i would convert this to class
public class myjson{
public string Name { get; set;}
public string Password { get; set;}
}
then with reflection call on the property
public GetValue(this myjson o, string propertyName){
return o.GetType().GetProperty(propertyName).GetValue(o);
}
in Jsvascript i would just call this
var value = json[0][property]
I hop this could help you
hello I think this can help you, I made a small example by picking up an answer written in Ajax and writing it in the console.
Look at the function in success, I think that's what you're looking for
function formToJSON(form) {
var obj = {};
var elements = form.querySelectorAll("input, select, textarea");
for (var i = 0; i < elements.length; ++i) {
var element = elements[i];
var name = element.name;
var value = element.value;
if (name) {
obj[name] = value;
}
}
return obj;
}
function test(id, url, method) {
var data = formToJSON(document.getElementById(id));
$.ajax({
type: method,
url: url,
data: data,
success: function (output, status, xhr) {
var response = JSON.parse(xhr.responseText);//<--- here is your JSON
for (var item in response) { // and set for to print indivual
console.log(item+' '+response[item]);
}
console.log(response);
},
cache: false
});
}

Kendo UI hidecolumn/showcolumn performance with many columns

I am trying to hide and show columns in my grid using Kendo UI hidecolumn and showcolumn methods, it works however it looks like the grid lags in showing and hiding column when there are many columns in grid. I have about 50 columns in my grid. Also after hiding the columns, the column doesn't realign in the grid even after using refresh method of the grid.
Does anyone know what's an alternative way to hide/show column without loosing the performance in the grid?
Thanks.
Sanjeev
Well, first of all, you just need to know, that columns in grid is nothing more than usual array. So you can create this array separately and assign into grid configuration.
I done it for configuration of whole grid but I try show only columns part, because example will be relative long because I will try show all important methods. Anyway I hope it helps you.
So process can be (but don't have to) be something like this:
Prepare database table. If you need save only visible/hid value, you can be satisfied with basic table like this:
CREATE TABLE dbo.TableSettings(
Id INT PRIMARY KEY IDENTITY,
[Key] VARCHAR(MAX) NOT NULL,
Name VARCHAR(MAX) NULL,
Value BIT NULL );
In my case table has more columns but for save this information this is enough. [Key] is table name in my case (dbo.[User] for example), Name is name of column (FirstName for example) and Value is Visible/hid (1/0).
Now you need to load columns settings from database and save it into array witch will be assigned into grid config.
RunSynchronousAjax(address, null, function (e) {
var options = JSON.parse(e.Config);
var columns = options.Columns;
//This part is needed only if you have some special cases which are prepared on server. It is because on server you cannot assign function like in javascript but you have to assign only name of function which need to be eval in javascript.
for (var i = 0; i < options.columns.length; i++) {
options.columns[i].filterable.ui = eval(options.columns[i].filterable.ui);
if (options.columns[i].filterable.itemTemplate != undefined) {
options.columns[i].filterable.itemTemplate = eval(options.columns[i].filterable.itemTemplate);
}
}
}, defaultErrorCallBack);
Note: RunSynchronousAjax is my helper method for processign ajax request because I didn't want write it everztime I need it. It looks like this:
function RunSynchronousAjax(url, data, successCallback, errorCallback) {
jQuery.ajax({
contentType: 'application/json; charset=utf-8',
url: url,
data: data,
type: "POST",
cache: false,
success: function (json) {
successCallback(json);
},
error: function (data) {
errorCallback(data);
},
async: false
});
}
function defaultErrorCallback(data) {
alert("Unexpected error. Please, try press CTRL+F5.");
}
This function is way how I load config for table, now let's look on method in controller.
public JsonResult GetSetting()
{
KendoGrid grid = new KendoGrid();
grid.PrepareColumns();
string json = JsonConvert.SerializeObject(grid);
return Json(new
{
Config = json
});
}
Objects looks like this
public class KendoGrid
{
...
private List<Column> _Columns = new List<Column>();
[JsonProperty("columns")]
public List<Column> Columns
{
get { return this._Columns; }
set { this._Columns = value; }
}
...
}
public class Column
{
[JsonProperty("field")]
public string Field { get; set; }
[JsonProperty("title")]
public string Title { get; set; }
[JsonProperty("type")]
public string Type { get; set; }
[JsonProperty("width")]
public string Width { get; set; }
[JsonProperty("filterable")]
public object Filterable { get; set; }
[JsonProperty("template")]
public string Template { get; set; }
[JsonProperty("order")]
public int Order { get; set; }
[JsonProperty("format")]
public string Format { get; set; }
.... and more ... just what you need
public Column(
string field,
string title = null,
string type = "string",
string width = null,
string template = null,
object filterable = null,
string format = null,
...)
{
this.Field = field;
this.Title = title ?? field;
this.Type = type;
this.Width = width;
this.Template = template;
this.Order = order;
this.Format = format;
....
}
In point 3 there is method PrepareColumns, it looks like this
public void PrepareColumns()
{
var listOfColumns = TableSettings.GetColumns("dbo.TableName");
this.Columns.AddNotNull(Column.GetColumn<ObjectWhichIsDisplayedInGrid>(x => x.Id, listOfColumns,
type: "number",
width: "140px",
...));
this.Columns.AddNotNull(Column.GetColumn<ObjectWhichIsDisplayedInGrid>(x => x.Name, listOfColumns,
width: "250px",
...));
.....
}
//This method is based on you, It just load records from db...
public static List<TableSettings> GetColumns(string key)
{
List<TableSettings> result = new List<TableSettings>();
var query = Sql.Builder
.Select("*")
.From("dbo.TableSettings")
.Where("[Key] = #0", key)
.OrderBy("OrderInTable");
using (IDatabase db = DbConnection.Connect())
{
result = db.Fetch<TableSettings>(query);
}
return result;
}
public static Column GetColumn<T>(
Expression<Func<T, object>> expression,
List<TableSettings> settings,
string type = "string",
string width = null,
string template = null,
...)
{
var fieldName = PropertyNameHelper.PropertyName<T>(expression);
var fieldDescription = PropertyNameHelper.PropertyDescription<T>(expression);
var column = settings.Where(c => c.Name.Replace(" ", string.Empty).ToLower() == fieldName.Replace(" ", string.Empty).ToLower()).FirstOrDefault();
Column col = new Column(
field: fieldName,
title: fieldDescription,
type: type,
....);
return col;
}
public static string PropertyName<T>(Expression<Func<T, object>> expression)
{
return GetPropertyName(expression);
}
public static string PropertyDescription<T>(Expression<Func<T, object>> expression)
{
var propertyName = GetPropertyName(expression);
PropertyInfo prop = typeof(T).GetProperty(propertyName);
if (prop.IsDefined(typeof(DisplayAttribute), false))
{
return (prop.GetCustomAttribute(typeof(DisplayAttribute), false) as DisplayAttribute).Name;
}
return propertyName;
}
That's it. First 5 points is about load columns configuration from database. What is saved as not visible, will not be loaded so kendo grid will know only about columns which are visible.
Now, I have talked about my own columnMenu. It is only usual popup window with options. Important is that grid has set columnMenu to false, so default functionality is off. I have added button into toolbar and click event has opened kendoWindow where I had checkboxes with columns names. I can check what I want to display and after popup is closed/confirmed, some ajax request is called - it is saved into database and grid is refreshed.
Anyway mainly it can gives you idea, I believe there is much more solutions for this. If you find way how to create columns array dynamically you will win.

Knockout MVC, bind model & add object to model

How can I add an item to a List<ComplexObject> with KnockoutJS?
This is my model:
public class MyModel
{
public List<User> Users { get; set; }
}
public class User
{
public int Id { get; set; }
public string Name { get; set; }
}
This is the client side script:
<script type="text/javascript">
var viewModel = ko.mapping.fromJS(#Html.Raw(Json.Encode(Model)));
ko.applyBindings(viewModel);
// attempt:
var newUser = [{ "Id": "13", "Name": "John" }];
</script>
How do I add newUser to the the viewModel?
I would do it in the following manner.
Create a User object
Create a mapping that maps your returned object to your new User object
Use a simple push to add a new User object
Please see full code below with comments
// 1. Create a User object
var User = function (Id, Name) {
self = this;
self.Id = Id;
self.Name = Name;
}
// 2. Create a mapping
var mapping = {
'Users': {
create: function(options) {
return new User(options.data.Id, options.data.Name);
}
}
}
var data = #Html.Raw(Json.Encode(Model));
var viewModel = ko.mapping.fromJS(data, mapping);
// output to verify binding
console.log(viewModel);
// 3. Add the new User object
viewModel.Users.push(new User(2, "Jim"));
// output to verify added user
console.log(viewModel.Users());
Update:
Here is a jsfiddle with it working against a list:
http://jsfiddle.net/6qsjz/12/
Update 2
The null issue seems to be that you are not initialising the collection, add a constructor to your model like this:
public MyModel()
{
Users = new List<User>();
}
See this fiddle...
http://jsfiddle.net/6qsjz/4/
It's a little more like you've got. The view model element, along with your rawData should be defined before your bindings are applied.
var rawData = { "OtherStuff": { }, "User": {"id": "1", "name": "Bob"} }
....
viewModel = new ViewModel(rawData);
ko.applyBindings(viewModel, document.getElementById('domElementToBind'));
I then showed 2 different examples of creating your objects. Check out the fiddle and follow up with any further questions.
-----EDITED-----
Here's the update so you can add more users. The key was just to make the User --> Users as an observable array and start pushing new users to it.
http://jsfiddle.net/6qsjz/13/
self.newUser = new User();
self.addUser = function() {
self.Users.push(self.newUser);
}
-----EDITED-----
Oops. That's what I get for not looking both ways.
http://jsfiddle.net/6qsjz/17/
self.addUser = function() {
self.Users.push(new User(self.newUser.id(), self.newUser.name()));

How can I map the names of an array of objects to change the field names?

I am sending data from my client to a method on my WebApi controller that accepts a class of ResponseFromClient. As it's WebApi this handles all the conversion from JSON and changes any field names to match the case convention differences between javascript and C#:
public class ResponseFromClient
{
public int QuestionId { get; set; }
public ICollection<AnswerDetail> Answers { get; set; }
public string Task { get; set; }
}
public class AnswerDetail
{
public int AnswerId { get; set; }
public string Text { get; set; }
public bool? Correct { get; set; }
public bool? Response { get; set; }
}
In Javascript I have an array called ans with each element looking like this:
qs.ans[index].id = element.answerId;
qs.ans[index].c = null;
qs.ans[index].r = false;
qs.ans[index].text = element.text;
I need to send the contents of a Javascript object responseFromClient to the C# server program:
var responseFromClient = {
questionId: qs.q,
answers: qs.ans,
task: task
};
$http({
method: 'POST',
url: url,
data: responseFromClient
})
Is there a simple way that I can set the answers field in the javascript variable responseFromClient so that it receives an array that contains objects that map to the AnswerDetail class. In other words I need to change it so that the answers gets and array of objects that are like this:
old > new
id > AnswerID
c > Correct
t > Text
r > Response
I was thinking to do it like I do where I remap qs.q > questionId. However ans is an array so I am not sure how to do this.
Is it not easier allround to map the object onto the class in your JavaScript
qs.ans[index].answerId = element.answerId;
qs.ans[index].correct = null;
qs.ans[index].response = false;
qs.ans[index].text
or
in the ajax call
data: { "answerId" : responseFromClient.id,
"correct": responseFromClient.c,
"response": responseFromClient.t,
"text": responseFromClient.text }
You can simply remap the values you want with arrays of old => new keys. There are more advanced ways of doing this, but I don't know all the details of your case...
function remap(obj, old_keys, new_keys){
var len = old_keys.length;
var new_obj = {};
for (var i = 0; i < len; i++) {
new_obj[new_keys[i]] = obj[old_keys[i]];
}
return new_obj;
}
var len = ans.length;
var old_keys = ["id", "c", "r", "text"];
var new_keys = ["AnswerId", "Correct", "Response", "Text"]
for (var i = 0; i < len; i++) {
ans[i] = remap(ans[i], old_keys, new_keys);
}

JayData one to many projections

I want to use jaydata JSLQ (JavaScript Language Query) to flatten a list of Post with one-to-many PostData into my ViewModel
My EF Entity looks like this:
public partial class Post
{
public Post()
{
this.PostData = new HashSet<PostData>();
}
public int Id { get; set; }
public virtual ICollection<PostData> PostData { get; set; }
}
My database contains these records:
Table: Post
Id;...
1;...
Table: PostData
Id;PostId;FieldType; FieldValue
1; 1; 10; "foo"
2; 1; 12; "bar"
3; 1; 34; "blah"
I want my view model in the client to look like this:
{id:1, title:'foo'}
That means, i want to put a filter on PostData that returns only FieldName==10, and i want to flatten that to a simple object.
How would I do that?
context.Posts.toArray(function(posts){console.dir(posts);})
returns an array of post objects. what next?
This is achieved witht he SelectMany() function in EF and on this approach is not yet supported by JayData. You can however achieve the same output with directly querying aganst PostData and filtering on Post attributes.
context.PostDatas
.filter( function(pd) { return pd.FieldType == 10 } )
.map( function(pd) { return {
PostID: pd.Post.Id,
PostDataId: pd.Id,
Title: pd.FieldValue }})
.toArray( ... )

Categories

Resources