slickgrid - grid.getDataItem(0), dataView.getItem(0) and .dataView.getItemByIdx(0) returning reference - slickgrid

I'm trying to duplicate a row, but change like one column.
So I do something like this:
var item = myGrid.grid.getDataItem(rowIndex);
item.id=123;
myGrid.dataView.addItem(item);
My issue is that if I am duplicating the row at index 0, when I do:
item.id = 123;
It actually makes id of the row at index 0 as 123 as well as the new line.
Is there a way to get the data and not get the actual reference to the row?
Thanks!

In this case, I would use the jQuery $.extend method to create a new object:
var newItem = {};
$.extend(newItem, item);
newItem.id=123;
myGrid.dataView.addItem(newItem);

Related

LinqToExcel - Need to start at a specific row

I'm using the LinqToExcel library. Working great so far, except that I need to start the query at a specific row. This is because the excel spreadsheet from the client uses some images and "header" information at the top of the excel file before the data actually starts.
The data itself will be simple to read and is fairly generic, I just need to know how to tell the ExcelQueryFactory to start at a specific row.
I am aware of the WorksheetRange<Company>("B3", "G10") option, but I don't want to specify an ending row, just where to start reading the file.
Using the latest v. of LinqToExcel with C#
I just tried this code and it seemed to work just fine:
var book = new LinqToExcel.ExcelQueryFactory(#"E:\Temporary\Book1.xlsx");
var query =
from row in book.WorksheetRange("A4", "B16384")
select new
{
Name = row["Name"].Cast<string>(),
Age = row["Age"].Cast<int>(),
};
I only got back the rows with data.
I suppose that you already solved this, but maybe for others - looks like you can use
var excel = new ExcelQueryFactory(path);
var allRows = excel.WorksheetNoHeader();
//start from 3rd row (zero-based indexing), length = allRows.Count() or computed range of rows you want
for (int i = 2; i < length; i++)
{
RowNoHeader row = allRows.ElementAtOrDefault(i);
//process the row - access columns as you want - also zero-based indexing
}
Not as simple as specifying some Range("B3", ...), but also the way.
Hope this helps at least somebody ;)
I had tried this, works fine for my scenario.
//get the sheets info
var faceWrksheet = excel.Worksheet(facemechSheetName);
// get the total rows count.
int _faceMechRows = faceWrksheet.Count();
// append with End Range.
var faceMechResult = excel.WorksheetRange<ExcelFaceMech>("A5", "AS" + _faceMechRows.ToString(), SheetName).
Where(i => i.WorkOrder != null).Select(x => x).ToList();
Have you tried WorksheetRange<Company>("B3", "G")
Unforunatly, at this moment and iteration in the LinqToExcel framework, there does not appear to be any way to do this.
To get around this we are requiring the client to have the data to be uploaded in it's own "sheet" within the excel document. The header row at the first row and the data under it. If they want any "meta data" they will need to include this in another sheet. Below is an example from the LinqToExcel documentation on how to query off a specific sheet.
var excel = new ExcelQueryFactory("excelFileName");
var oldCompanies = from c in repo.Worksheet<Company>("US Companies") //worksheet name = 'US Companies'
where c.LaunchDate < new DateTime(1900, 0, 0)
select c;

Can I refer to items within a LINQ result set by index?

I'm trying to work with a LINQ result set of 4 tables retrieved with html agility pack. I'd like to process each one slightly differently by setting a variable for each (switch statement below), and then processing the rows within the table. The variable would ideally be the index for each of the tables in the set, 0 to 3, and would be used in the switch statement and to select the rows. I haven't been able to locate the index property, but I see it used in situations such as SelectChildNode.
My question is can I refer to items within a LINQ result set by index? My "ideal scenario" is the last commented out line. Thanks in advance.
var ratingsChgs = from table in htmlDoc.DocumentNode
.SelectNodes("//table[#class='calendar-table']")
.Cast<HtmlNode>()
select table;
String rtgChgType;
for (int ratingsChgTbl = 0; ratingsChgTbl < 4; ratingsChgTbl++)
{
switch (ratingsChgTbl)
{
case 0:
rtgChgType = "Upgrades";
break;
case 1:
rtgChgType = "Downgrades";
break;
case 2:
rtgChgType = "Coverage Initiated";
break;
case 3:
rtgChgType = "Coverage Reit/ Price Tgt Changed";
break;
//This is what I'd like to do.
var tblRowsByChgType = from row in ratingsChgs[ratingsChgTbl]
.SelectNodes("tr")
select row;
//Processing of returned rows.
}
}
ElementAt does what you're asking for. I don't recommend using it in your example, though, because each time you call it, your initial LINQ query will be executed. The easy fix is to have ratingsChgs be a List or Array.
You can also refactor out the switch statement. It is overkill when you only need to iterate through a list of items. Here is a possible solution:
var ratingsChgs = from table in htmlDoc.DocumentNode
.SelectNodes("//table[#class='calendar-table']")
.Cast<HtmlNode>()
select table;
var rtgChgTypeNames = new List
{
"Upgrades",
"Downgrades",
"Coverage Initiated",
"Coverage Reit/ Price Tgt Changed"
};
var changeTypes = ratingsChgs.Zip(rtgChgTypeNames, (changeType, name) => new
{
Name = name,
Rows = changeType.SelectNodes("tr")
});
foreach( var changeType in changeTypes)
{
var name = changeType.Name;
var rows = changeType.Rows;
//Processing of returned rows.
}
Also, why not store your rating change types in the HTML doc? It seems odd to have table information defined in the business logic.

How to get the selected row ids sorted according to index in jqgrid?

I'm using
getGridParam('selarrrow');
to get the rows that are selected,where the method returns me the selected row ids according to their selection,but I want the ids according to their index.Do I have to write a method to sort the ids or is there a inbuilt method which returns me the selected row ids in order of their indexes.
thanks in advance
If you mean the index of the row in the grid then you have to resort the array or id returned by $("#gridId").jqGrid("getGridParam", "selarrrow"). You can use sort() method of Array with your custom sort function. You can just use the fact that ids are the ids of <tr> elements. So the DOM elements of <tr> has native implemented rowIndex property which you can get by $("#"+rowid)[0].rowIndex.
In the simplified form the code could be about the following
var selRowIds = $("#gridId").jqGrid("getGridParam", "selarrrow");
selRowIds.sort(function (id1, id2) {
// one can use document.getElementById alternatively
return $("#" + id1)[0].rowIndex - $("#" + id2)[0].rowIndex;
});
or you can use namedItem method instead
var $grid = $("#gridId"),
selRowIds = $grid.jqGrid("getGridParam", "selarrrow"),
rows = $grid[0].rows;
selRowIds.sort(function (id1, id2) {
return rows.namedItem(id1).rowIndex - rows.namedItem(id2).rowIndex;
});
Probably you should include more verification in the code to be sure that the item with id will be found and it has the rowIndex property.

Get IGrouping data in Repeater ItemDataBound

I am wanting to group news articles by year in a repeater. The format would be:
2010
list of articles
2011
List of Articles
My access layer returns a flat list of news articles, specifically List. Therefore, I am grouping them and binding them to the Repeater as follows:
events = DAL.GetEvents();
var groupedNewsList = from e in events
group e by e.StoryDate.Year
into g
select new {
Year = g.Key
, Events = g
};
rptEvents.DataSource = groupedNewsList;
rptEvents.DataBind();
The problem is trying to get the List from within the ItemDataBound event. So far, I have the following:
var data = e.Item.DataItem;
System.Type type = data.GetType();
// getting the year works fine
string year = (string)type.GetProperty("Year").GetValue(data, null).ToString();
// this returns something, but I can't access any properties. I need to get
//access to the contained List<News>
var newsList = type.GetProperty("Events").GetValue(data, null);
Any ideas?
Thanks in advance!
You don't have a List<News> - you just have a grouping. If you want a List<News>, you'll need to change your query, e.g.
var groupedNewsList = from e in events
group e by e.StoryDate.Year into g
select new { Year = g.Key, Events = g.ToList() };
Note that if you're using C# 4 you could do reflection rather more easily using dynamic typing:
dynamic data = e.Item.DataItem;
string year = data.Year.ToString();
List<News> newsList = data.Events;
Alternatively, you could avoid using an anonymous type in the first place - create your own GroupedNewsList type with Year and Events properties, populate that in your query, and then cast to it in your event handler.
The "sender" object in the ItemDataBound event is the repeater -- use it to get to the data-source. If the data-source has been grouped before binding, you can compare the current value to the previous value & hide the year-field if they are equal. Like this:
MyObject item = (MyObject)item.DataItem;
Repeater repeater = (sender as Repeater);
List<MyObject> items = repeater.DataSource as List<MyObject>;
Label lblGrouping = (Label)item.FindControl("lblGrouping");
if (item.ItemIndex == 0 || item.DateField.Year != items[item.ItemIndex - 1].DateField.Year) {
lblGrouping.Text = item.DateField.Year.ToString();
}
This worked for me, as I used a table with each row being one item, and the left-most column contained the "lblGrouping" control.

Update entity columns iterating through col list using LINQ

I can get column list from the table using LINQ like this:
OrderDataContext ctx = new OrderDataContext();
var cols = ctx.Mapping.MappingSource
.GetModel( typeof( OrderDataContext ) )
.GetMetaType( typeof( ProductInformation ) )
.DataMembers;
This gives me the list of columns, so I can do this:
foreach ( var col in cols )
{
// Get the value of this column from another table
GetPositionForThisField( col.Name );
}
So this all works, I can iterate through column list and pull the values for those columns from an another table (since the column names are the keys in that another table), so I don't have to do switch....or lot of if...then...
Now the question:
After I get these values, how do I populate the entity in order to save it back? I would normally go like this:
ProductInformation info = new ProductInformation();
info.SomeField1 = val1;
info.SomeField2 = val2;
ctx.ProductInformation.InsertOnSubmit( info );
ctx.SubmitChanges();
But how to use the same column collection from above to populate the columns while iterating over that, when there is no such thing as:
info["field1"].Value = val1;
Thanks.
Just fetch the object that you want to modofy, set the property and call SubmitChanges. There is no need to create a new object and insert it. The Context tracks your changed properties and generates the update statement accordingly. In your case you may want to set the properties via reflection rather than manually since you are reading them from another table.
You'll need to use reflection. Assuming you can get the PropertyInfo from the metadata:
PropertyInfo property = GetPropertyForThisField(col.Name);
property.SetValue(info, val1, null);

Resources