dynamically creating select elements and populating options from sharepoint list - c#

The code I wrote works, but it could be better. I am writing out the same function three times, one for each of the combo box elements. I am stuck on how to make this more efficient. I have looked at creating an object and putting each of the variables in an array, but I was not able to successfully get it working.
var csCategory = <%=csCategoryArray%>,
csKeyword = <%=csKeywordArray%>,
csEntity = <%=csEntityArray%>;
addOption = function (selectbox, text, value) {
var optn = document.createElement("OPTION");
optn.text = text;
optn.value = value;
selectbox.options.add(optn);
}
$(function () {
// Temp test stuff to populate option list
var selectObj = document.getElementById("combobox1")
if (selectObj) {
for (var i=0; i < csCategory.length;++i){
addOption(selectObj, csCategory[i], csCategory[i]);
}
}
});
$(function () {
// Temp test stuff to populate option list
var selectObj = document.getElementById("combobox2")
if (selectObj) {
for (var i=0; i < csKeyword.length;++i){
addOption(selectObj, csKeyword[i], csKeyword[i]);
}
}
});
$(function () {
// Temp test stuff to populate option list
var selectObj = document.getElementById("combobox3")
if (selectObj) {
for (var i=0; i < csEntity.length;++i){
addOption(selectObj, csEntity[i], csEntity[i]);
}
}
});

The obvious first step is to refactor out the shared code. So:
$(function () {
// Temp test stuff to populate option list
var selectObj = document.getElementById("combobox2")
if (selectObj) {
for (var i=0; i < csKeyword.length;++i){
addOption(selectObj, csKeyword[i], csKeyword[i]);
}
}
});
( ... etc ... )
becomes:
function populate(id, collection) {
var selectObj = document.getElementById(id)
if (selectObj) {
for (var i=0; i < collection.length;++i){
addOption(selectObj, collection[i], collection[i]);
}
}
}
$(function () {
populate ("combobox1", csCategory);
populate ("combobox2", csKeyword);
populate ("combobox3", csEntity);
});
I can't see any significant advantage at this stage of putting combobox1 and its siblings into an array, but it may be worthwhile revisiting this code if more comboboxes are added in the future.

Related

Get ViewData in View JQuery

I have a Generic List and I'm passing it as ViewData from my Controller to my .aspx View.
I need to get and iterate it with a Jquery Script.
How could I make this script works?
Regards
success: function (result) {
var myArray = new Array();
var myArray = '<%: ViewData["List"] %>';
for (var i = 0; i < myArray.length; i++) {
alert(i);
}
You can do something like this..
<script type="text/javascript">
#{ List<string> ss = (List<string>)ViewData["List"];}
var myArray = [
#for (int i = 0; i < ss.Count; i++)
{
#: #(ss[i]),
}
]
</script>
my syntax for razor view(you can do it for classic)
Try like this , push items of list view to the array of javascript, wrap below code in script tag
--script tag--
var jList = new Array();
#foreach (var item in ViewData["List"] as List<String>)
{
#:jList.push('#item'); // That will work if its a one letter string but It doesnt know that its a string untill you use ''
}
--script tag--
Ok if you are using just a list of strings then
this will do
$(document).ready(function () {
#{List<string> listFromController = (List<string>)ViewData["List"];}
var myArray = [
#for (int i = 0; i < listFromController.Count; i++)
{
#: '#(listFromController[i])',
}
]
});
But if you are passing list of another type rather than string like an student Employee or a user you will need the following
Please use the appropriate class that you have passed and the
properties suppose "UserName" could be "FirstName" "EmpId" or what ever
$(document).ready(function () {
#{ var listFromController = (List<KnockoutJSWebApi.Models.LoginViewModel>)ViewData["list"];}
var totalArray = [];
#for (int i = 0; i < listFromController.Count; i++)
{
<text>
var thisArray= {
'username': '#(listFromController[i].UserName)',
'password': '#(listFromController[i].Password)'
};
totalArray.push(thisArray);
</text>
}
});
Aspx View Engine syntax:
<script>
$(document).ready(function () {
<% List<string> listFromController = (List<string>)ViewData["List"]; %>
var myArray = [
<% for (int i = 0; i < listFromController.Count; i++){ %>
'<%: listFromController[i] %>',
<% } %>
]
debugger;
});
</script>
Problem solved.
I used a JsonResult method in my Controller and returned the needed values as:
Json(List, JsonRequestBehavior.AllowGet);
With that, I don't need to iterate the values because I assign them as datasource to my DropDownList control.
$("#Generic_FK").data("DropDownList").dataSource.data(result);
Hope to help other people with the same issue!
Server Side
public class users
{
public string name{ get; set; }
}
// in your controller code
ViewData["list"] = new List<users>(new users[] { new users()
{ name="prasad"}, new users() {name="raja"}});
Client Side
<script type="text/javascript">
$(function(){
var myitems=JSON.parse('#Html.Raw(Json.Encode(this.ViewData["list"]))');
$.each(myitems, function(index, item) {
var name = item.name;
});
});
</script>
i hope this may help you

How to loop all functions?

I am working on a project and I've got stuck :(.... I have 9 (nine) functions with the name:
getM1(), getM2(), getM3(), getM4()....getM5(). And all of these functions return a value.
Now I need to make a loop which checks the value of these functions. Something like this:
public void show()
{
for (int i = 1; i <= 9; i++)
{
if (obj.getM[i]() == 1)
{
.......;
}
}
}
Of course it shows me an error because the getM doesn't contain any index..
And I wanted to ask you, can you help me with this? Or does anybody have another idea how could I check all getM() functions?
Create an array of Func<int> delegates and use it to access your methods:
var functions = new Func<int>[9];
functions[0] = getM1;
functions[1] = getM2;
functions[2] = getM3;
// (...)
for (int i = 0; i <= 9; i++)
{
if (functions[i]() == 1)
{
;
}
}
What about putting the functions into an Array:
var functionList = new [] { obj.getM1, obj.getM2, ... };
And then loop at it
foreach (var f in functionList)
{
if (f() == 1)
...
}
Replace the methods with this:
int getM(int index)
If this and the other solutions suggested really don't make any sense, you can do what you want using reflection:
var t = obj.GetType();
for (int i = 1; i <= 9; i++)
{
var m = t.GetMethod("getM" + i);
int result = (int)m.Invoke(obj, null);
}
Make an array of Func<T>, where T is the return type of your functions. Then you would be able to call your functions more or less the way you described in your code.
For example, if your functions return int, you can do this:
Func<int>[] ems = new Func<int>[] {
() => obj.getM1(), () => obj.getM2(), () => obj.getM3()
, () => obj.getM4(), () => obj.getM5(), () => obj.getM6()
, () => obj.getM7(), () => obj.getM8(), () => obj.getM9()
};
foreach (Func<int> em in ems)
{
if (em() == 1)
{
.......;
}
}
public void Show()
{
Func<int>[] arr = new[]
{
obj.GetM1,
obj.GetM2,
...
};
foreach(Func<int> func in arr)
{
if (func() == 1)
{
//
}
}
}
You could store all of these methods in a list, loop over the list an execute them.
var funcList = new List<Func<int>>{ getM1, getM2, ... };
Then you can loop over the list and execute each method.
foreach(var func in funList)
{
if(func() == 1)
...
}

How to compute rank of IEnumerable<T> and store it in type T

I want to compute rank of element in an IEnumerable list and assign it to the member. But below code works only when called 1st time. 2nd time call starts from last rank value. So instead of output 012 and 012, I'm getting 012 and 345
class MyClass
{
public string Name { get; set; }
public int Rank { get; set; }
}
public void SecondTimeRankEvaluvate()
{
MyClass[] myArray = new MyClass[]
{
new MyClass() { Name = "Foo" },
new MyClass() { Name = "Bar" },
new MyClass() { Name = "Baz" }
};
int r = 0;
var first = myArray.Select(s => { s.Rank = r++; return s; });
foreach (var item in first)
{
Console.Write(item.Rank);
}
// Prints 012
Console.WriteLine("");
foreach (var item in first)
{
Console.Write(item.Rank);
}
// Prints 345
}
I understand that the variable r is being captured (closure) and reused when called 2nd time. I don't want that behavior. Is there any clean way to compute rank and assign it?
Also r variable (in actual code) isn't in the same scope where foreach loop is present. It is in a function which returns var first
var first = myArray.Select((s, i) => { s.Rank = i; return s; });
LINQ uses lazy evaluation and runs the Select part every time you use myArray.
You can force evaluation to happen only once by storing the result in a List.
Change
var first = myArray.Select(s => { s.Rank = r++; return s; });
to
var first = myArray.Select(s => { s.Rank = r++; return s; }).ToList();
Another way would be to join myArray with a new sequence using Zip every time, like this
var first = myArray.Zip(Enumerable.Range(0, int.MaxValue), (s, r) =>
{
s.Rank = r;
return s;
});
You shouldn't use LINQ if you're not querying the collection.
To update each item in an array, use a for loop:
for (int i = 0; i < myArray.Length; i++)
{
myArray[i].Rank = i;
}
To update each item in an enumerable, use a foreach loop:
int r = 0;
foreach (var item in myArray)
{
item.Rank = r++;
}

paging a heavy document using jquery and mvc

I have a html document but it's size is about 5MB.
Here is my code "../Product/index?page=1" it generates 5MB html :
Plugin url : http://andersonferminiano.com/jqueryscrollpagination/
<script type="text/javascript">
$(function () {
$('#content').scrollPagination({
'contentPage': '../Product/index?page=1',
'contentData': {},
'scrollTarget': $(window),
'heightOffset': 10,
'beforeLoad': function () {
$('#loading').fadeIn();
},
'afterLoad': function (elementsLoaded) {
$('#loading').fadeOut();
var i = 0;
$(elementsLoaded).fadeInWithDelay();
if ($('#content').children().size() > 100) {
$('#nomoreresults').fadeIn();
$('#content').stopScrollPagination();
}
}
});
$.fn.fadeInWithDelay = function () {
var delay = 0;
return this.each(function () {
$(this).delay(delay).animate({ opacity: 1 }, 200);
delay += 100;
});
};
});
</script>
<!--_____________________________________________________________________-->
#{
// here is "Product/index" Code
if (Request.QueryString.HasKeys())
{
int iPage = Request.QueryString["page"].AsInt();
using (var db = new PNUBOOKIR.Models.KowsarSiteEntities())
{
var queries = from n in db.vwGood
select n;
long counter = 0;
for (int i = 1; i <= iPage; i++)
{
foreach (var q in queries)
{
counter++;
<li style="opacity: 0; -moz-opacity: 0; filter: alpha(opacity=0);">
<p>
#counter
</p>
</li>
}
}
}
}
}
I don't want to load it complete when the scroll goes down it should load 10 other "li" element
I do not simulate so heavy page, but I have an other way to load page. Maybe, it can be a reference for you.
Separate each page request at action side, and return for only one page content.
Collect "style" content to css class, to reduce page content.
Improve performance of LINQ with PLINQ.
I notice the code output every page content.
var queries = from n in db.vwGood select n;
long counter = 0;
for (int i = 1; i <= iPage; i++)
{
foreach (var q in queries)
{
counter++;
}
}
I suggest you can
modify LINQ with Paging function.
Update LINQ as PLINQ to improve performance. I add AsParallel() after db.vwGood, I am not sure what db.vwGood instance and wish this modify can be good.
Not return HTML content in Razor View, but in Action.
Pseudo code of Action is as below,
// iAmount is record amount in each page.
int iAmount = 50;
// queries is only the iPage content
// but not all of content from page one to page iPage.
var queries = (from n in db.vwGood.AsParallel() select n)
.Skip(iPage - 1).Take(iAmount);
long counter = 0;
string strContent = string.Empty;
foreach (var q in queries)
{
counter++;
// Generate Cotnent here.
strContent += #"<li class='YourClassName'><p>#counter</p></li>"
}
return Content(strContent)
When ShowMore button is clicked, ShowMore_OnClick() is performanced.
<input type="button" style="width: 100%" id="BtnShowMore" value="MORE"
onclick="return ShowMore_OnClick();" />
This is JavaScript for Loading function.
I notice you do not use button to control content display, but scrollPagination. You can modify the JavaScript to suit with scrollPagination plugin. The thinking of code structure is same.
var PageNO = 1;
function ShowMore_OnClick() {
var BtnShowMore = document.getElementById("BtnShowMore");
BtnShowMore.value = "Loading...";
jQuery.post(
"/Home/GetHomeEventAjax/",
{ "PageNO": PageNO + 1 },
function (data, states) {
if (states == "success") {
var EventListArea = document.getElementById("EventListArea");
var newCommentItem = document.createElement("DIV");
newCommentItem.setAttribute("ID", "EventItem");
newCommentItem.innerHTML = data;
EventListArea.appendChild(newCommentItem);
PageNO = PageNO + 1;
BtnShowMore.value = "More";
}
}
);
}

Can I access the index from within a foreach?

In PHP I can do this:
$list = array("element1", "element2");
foreach ($list as $index => $value) {
// do stuff
}
In C# i can write:
var list = new List<string>(){ "element1", "element2" };
foreach (var value in list)
{
// do stuff ()
}
But how can I access the index-value in the C# version?
Found multiple solutions on: foreach with index
I liked both JarredPar's solution:
foreach ( var it in list.Select((x,i) => new { Value = x, Index=i }) )
{
// do stuff (with it.Index)
}
and Dan Finch's solution:
list.Each( ( str, index ) =>
{
// do stuff
} );
public static void Each<T>( this IEnumerable<T> ie, Action<T, int> action )
{
var i = 0;
foreach ( var e in ie ) action( e, i++ );
}
I chose Dan Finch's method for better code readability.
(And I didn't need to use continue or break)
I'm not sure it's possible to get the index in a foreach. Just add a new variable, i, and increment it; this would probably be the easiest way of doing it...
int i = 0;
var list = new List<string>(){ "element1", "element2" };
foreach (var value in list)
{
i++;
// do stuff ()
}
If you have a List, then you can use an indexer + for loop:
var list = new List<string>(){ "element1", "element2" };
for (int idx=0; idx<list.Length; idx++)
{
var value = list[idx];
// do stuff ()
}
If you want to access index you should use for loop
for(int i=0; i<list.Count; i++)
{
//do staff()
}
i is the index

Categories