My problem is that the calendar is rendering before the JSON response is sent to the browser. In other words when we get to the array search my array is empty. How would I fix this?
UPDATED: I gave up on trying to request more dates on month change, so now I just get about 6 months worth of events on my first call and display it all at once. Below is the working code.
$(document).ready(function () {
var actionCalDates = [];
//var orgID = 0;
var currentDate = new Date();
dateCount = 0;
getDates(1, currentDate.getMonth(), currentDate.getFullYear());
function displayCalendar() {
$("#calendar").datepicker({
dateFormat: 'dd/mm/yyyy',
beforeShowDay: function (thedate) {
var theday = (thedate.getMonth() + 1) + "/" + thedate.getDate() + "/" + thedate.getFullYear();
//console.log("Before the if my array contains: " + actionCalDates);
if ($.inArray(theday, actionCalDates) == -1) {
//console.log(theday + " Not Found");
return [false, "", ""];
} else {
//console.log(theday + " Found");
return [true, "specialDate", "Actions Today"];
}
}
});
}
function getDates(orgID, month, year) {
dateCount += 1;
if (dateCount < 4) {
$.ajax({
url: "/Calendar/getEvents",
data: {
'orgID': orgID,
'month': month,
'year': year
},
type: "GET",
dataType: "json",
success: function (result) {
//console.log(result);
for (var i in result) {
actionCalDates.push(result[i]);
//console.log("Pushed to the array: " + actionCalDates[i]);
}
//console.log("Array currently holds: " + actionCalDates);
displayCalendar();
}
});
}
}
});
Code Behind C# controller:
public JsonResult getEvents(int orgID, int month, int year)
{
DateTime orgDate = Convert.ToDateTime(month + "/" + orgID + "/" + year);
var fromDate = orgDate;
var toDate = orgDate.AddMonths(7); //last month and the next 6 months
var events = db.Events.Where(e => e.StartDate >= fromDate && e.EndDate <= toDate).ToArray();
var eventlist = from e in events
select new
{
date = e.StartDate.ToString(),
};
List<string> EventDates = new List<string>();
foreach (var currentEvent in eventlist)
{
DateTime dt;
dt = Convert.ToDateTime(currentEvent.date.ToString());
EventDates.Add(dt.Month + "/" + dt.Day + "/" + dt.Year);
}
return Json(EventDates, JsonRequestBehavior.AllowGet);
}
Why not putting the $("#calendar").datepicker({ call inside the ajax success: handler:
success: function (result) {
console.log(result);
for (var i in result) {
actionCalDates.push(result[i]);
console.log("Pushed to the array: " + actionCalDates[i]);
}
//actionCalDates = actionCalDates.concat(result);
console.log("Array currently holds: " + actionCalDates);
//getDates(orgID, month + 1, year);
//getDates(orgID, month - 1, year);
//Now we have filled the array, let's create our calendar..
$("#calendar").datepicker({
....
}
Put the code that renders the calendar into some arbitrary function, then put a call to that function in your ajax({success: }) function
ie
function renderCalendar(){
$("#calendar").datepicker({
...
});
}
success: function (result) {
...
renderCalendar();
}
I think the method you want is called onChangeMonthYear.
I have used it in a tutorial I wrote up. It's probably not the prettiest code ever written however it does seem to be basically working.
Related
In my view, I have checkboxes and some data displayed and button on each row to approve or reject requests put up.
I want to send my integer array to my action method but this cannot be done by just sending it to action query parameters and it would be like the picture below:
public int[] Ids
{
get { return new int[] { 1, 2, 3 }; }
set {}
}
public ActionResult Approval([ModelBinder(typeof(IntArrayModelBinder))] int[] ids)
{
...
return View(...);
}
#Html.ActionLink("Approve", "Approval", new {id = item.Ids, approvalAction = "approve"})
How do I implement the checkboxes to be checked and hover of the approve/reject actionlink will show the url with ../ids=1&ids=2&ids=3 instead of System.Int32[]?
Option 1: Send your array as a comma-separated string and then split them in your action like this :
#Html.ActionLink("Approve", "Approval", new { id = string.Join("," , Ids), approvalAction = "approve" } )
your action :
public ActionResult YourAction(string id , string approvalAction)
{
var ids = id.Split(',');
//rest of your action method business
}
Option 2:
another way to achieve your exactly url is to create your URL like this :
var baseUrl = Url.Action("YourAction", "YourController", null, Request.Url.Scheme);
var uriBuilder = new UriBuilder(baseUrl);
uriBuilder.Query = string.Join("&", Ids.Select(x => "ids=" + x));
string url = uriBuilder.ToString();
url += "&approvalAction=approve"
and your action would be like this :
public ActionResult YourAction(int[] ids , string approvalAction)
{}
<script>
function multiSelect(selectedArray, action) {
if (selectedArray[0] === undefined) {
alert("You have not selected any employee");
}
//example url
//..?ids=1&ids=2&ids=3&aprovalAction=approve
else {
var param = "";
var currUrl = "";
var idUrl = "";
idUrl = "ids=" + selectedArray[0];
for (var i = 1; i < selectedArray.length; ++i) {
idUrl += "&ids=" + selectedArray[i];
}
switch (action) {
case "Approve":
param = "approve";
break;
case "Reject":
param = "reject";
break;
}
currUrl = "approvalAction=" + param;
window.location.href = "?" + idUrl + "&" + currUrl;
}
}
</script>
<script>
$('#MultiApproveBtn').click(function () {
var selected = $('input[type=checkbox]:checked').map(function (_, el) {
return $(el).val();
}).get();
var x = document.getElementById("MultiApproveBtn").value;
//alert(selected);
multiSelect(selected, x);
})
</script>
<script>
$('#MultiRejectBtn').click(function () {
var selected = $('input[type=checkbox]:checked').map(function (_, el) {
return $(el).val();
}).get();
var x = document.getElementById("MultiRejectBtn").value;
//alert(selected);
multiSelect(selected, x);
})
</script>
I need help to pass parameters through JQuery's autocomplete. I have an input:
<input type="text" class="form-control mb-2 mr-sm-2 mb-sm-0" name="searchName" id="searchName" placeholder="Nom et/ou prénom" />
inside a form. When you type, an jquery autocomplete function launches a search in Active Directory and shows result in the drop down list:
$(document).ready(function () {
$("#searchName").autocomplete({
source: function (request, response) {
$.ajax({
url: "/Home/SearchUserWhileTyping",
type: "GET",
data: { name: $("#searchName").val() },
contentType: "application/json;charset=utf-8",
dataType: "json",
success: function (data) {
$("#searchName").html(''),
response($.map(data, function (item) {
return {
label: item
}
}));
}
});
},
minLength: 4
})
});
$(document).ready(function(){
$('#searchName').on('autocompletechange change', function () {
$('#searchValue').html('You selected: ' + this.value);
}).change()});
For now I could only do it after a form validation: form is validated -> I load the users found and their unique id -> click on one link and it shows the user info thanks to their unique id passed through. What I want to do is: If you click on one of the autocomplete choices, it directly shows the information of your user.
Here is the code for the search while you type:
[HttpGet]
public ActionResult SearchUserWhileTyping(string name)
{
ADManager adManager = new ADManager();
List<string> lastName = adManager.SearchUserByName(name);
List<string> splitList = new List<string>();
if (lastName != null)
{
if (lastName.Count <= 10)
{
int inc = 0;
foreach(string splitter in lastName)
{
if (inc % 2 == 1)
{
splitList.Add(splitter);
}
inc++;
}
return Json(splitList, JsonRequestBehavior.AllowGet);
}
}
return null;
}
I use a splitter because another function allows me to search AD and returns several parameters (which will then be useful to immediately find a user by its unique id, that's my difficulty).
This calls the following function:
public List<string> SearchUserByName(string name)
{
try
{
DirectoryEntry ldapConnection = createDirectoryEntry();
DirectorySearcher search = new DirectorySearcher(ldapConnection);
var sidInBytes=new byte[0];
//anr permet de chercher tout utilisateur contenant "name"
search.Filter = "(&(objectClass=user)(anr=" + name + "))";
//search.Filter = "(&(objectClass=User) (name=" + name + "*))";
search.PropertiesToLoad.Add("displayName");
search.PropertiesToLoad.Add("distinguishedName");
resultCollection = search.FindAll();
if (resultCollection.Count == 0)
{
return null;
}
else
{
foreach(SearchResult sResult in resultCollection)
{
if (sResult.Properties["distinguishedName"][0].Equals(null) ||
sResult.Properties["displayName"][0].Equals(null))
continue;
displayName.Add(sResult.Properties["distinguishedName"][0].ToString());
displayName.Add(sResult.Properties["displayName"][0].ToString());
}
}
ldapConnection.Close();
ldapConnection.Dispose();
search.Dispose();
return displayName;
}
catch (Exception e)
{
Console.WriteLine("Exception caught:\n\n" + e.ToString());
}
return null;
}
Finally, when I have my list of users, I can click on their link and I load info about the user using this function:
public List<KeyValuePair<string,string>> GetUserInfoBySAMAN(string sAMAccountName)
{
try
{
DirectoryEntry ldapConnection = createDirectoryEntry();
DirectorySearcher search = new DirectorySearcher(ldapConnection);
search.Filter = "(sAMAccountName=" + sAMAccountName + ")";
search.PropertiesToLoad.Add("objectSID");
search.PropertiesToLoad.Add("displayName");
search.PropertiesToLoad.Add("memberOf");
search.PropertiesToLoad.Add("description");
search.PropertiesToLoad.Add("accountExpires");
search.PropertiesToLoad.Add("sAMAccountName");
result = search.FindOne();
///Conversion du SID en chaine de caractères
var sidInBytes = (byte[])result.Properties["objectSID"][0];
var sid = new SecurityIdentifier(sidInBytes, 0);
String time;
if (result.Properties["accountExpires"][0].ToString().Equals("0")|| result.Properties["accountExpires"][0].ToString().Equals("9223372036854775807"))
{
time = "Jamais";
}
else
{
///Conversion de la date en entier puis en date
DateTime dt = new DateTime(1601, 01, 02).AddTicks((Int64)result.Properties["accountExpires"][0]);
time = dt.ToString();
}
string desc="";
if (result.Properties.Contains("description"))
{
desc = result.Properties["description"][0].ToString();
}
else
{
desc = "Pas de description disponible";
}
userInfo = new List<KeyValuePair<string, string>>()
{
new KeyValuePair<string, string>("displayName",result.Properties["displayName"][0].ToString()),
new KeyValuePair<string, string>("memberOf", result.Properties["memberOf"][0].ToString()),
new KeyValuePair<string, string>("accountExpires",time),
new KeyValuePair<string, string>("description",desc),
new KeyValuePair<string, string>("sid",sid.ToString()),
new KeyValuePair<string, string>("sAMAccountName",result.Properties["sAMAccountName"][0].ToString())
/*lastName.Add(result.Properties["displayName"][0].ToString());
lastName.Add(result.Properties["memberOf"][0].ToString());
lastName.Add(sid.ToString());
lastName.Add(result.Properties["accountExpires"][0].ToString());
lastName.Add(result.Properties["description"][0].ToString());*/
};
return userInfo;
}
catch(Exception e)
{
Console.WriteLine("Exception caught:\n\n" + e.ToString());
}
return null;
}
That last function doesn't work if I change sAMAccountName by distinguishedName because apparently this attribute cannot be used like that. I want to use distinguishedName and immediately have my object.
So what I need is to search while I type, and if I select one of the proposed choices, validating the form immediately send me to user info page.
Thanks for your help, hope it is clear enough
Edit I added a 2nd script that can get the value of selected item, but I need the data passed through the controller
If I understood right, autocomplete method has select event.
$(document).ready(function () {
$("#searchName").autocomplete({
source: function (request, response) {
$.ajax({
url: "/Home/SearchUserWhileTyping",
type: "GET",
data: { name: $("#searchName").val() },
contentType: "application/json;charset=utf-8",
dataType: "json",
success: function (data) {
$("#searchName").html(''),
response($.map(data, function (item) {
return {
label: item
}
}));
},
select: function(e, ui)
{
//Just Example
$.get("UserController", {ID: ui.Id}).done(
function(data){
});
//Write your ajax post or get method
//that fetches user data directly as soon as
//the item in list clicked
}
});
},
minLength: 4
})
});
Edit: I saw your edit, so that you can use your GetUserInfoBySAMAN function for ajax get request inside select event (instead where I wrote "UserController"), and you have work for binding return data to the inputs or labels as well.
I have a data content witch contains complex data I just need index names which seem in Dynamic View in data. In debug mode I can see the datas but cant get them..
You can see the contents of data in image below):
if(hits.Count() > 0)
{
var data = hits.FirstOrDefault().Source;
var dataaa = JsonConvert.DeserializeObject(hits.FirstOrDefault().Source);
}
I found a solution with checking if selected index has documents; if yes,
I take the first document in index, and parse it to keys(field names) in client.
here is my func:
[HttpPost]
public ActionResult getIndexFields(string index_name)
{
var node = new Uri("http://localhost:9200");
var settings = new ConnectionSettings(
node,
defaultIndex: index_name
);
var esclient = new ElasticClient(settings);
var Documents = esclient.Search<dynamic>(s => s.Index(index_name).AllTypes().Source());
string fields = "";
if (Documents.Documents.Count() > 0)
{
fields = JsonConvert.SerializeObject(Documents.Documents.FirstOrDefault());
var data = Documents.Documents.FirstOrDefault().Source;
return Json(new
{
result = fields,
Success = true
});
}
return Json(new
{
result = "",
Success = false
});
}
and my js:
$.ajax({
url: "getIndexFields?index_name=" + $(this).val(),
type: "POST",
success: function (data) {
if (data.Success) {
var fields = JSON.parse(data.result);
var fields_arr = [];
$.each(fields, function (value, index) {
fields_arr.push(
{
id: value,
label: value
})
});
options.filters = fields_arr;
var lang = "en";//$(this).val();
var done = function () {
var rules = $b.queryBuilder('getRules');
if (!$.isEmptyObject(rules)) {
options.rules = rules;
}
options.lang_code = lang;
$b.queryBuilder('destroy');
$('#builder').queryBuilder(options);
};
debugger
if ($.fn.queryBuilder.regional[lang] === undefined) {
$.getScript('../dist/i18n/query-builder.' + lang + '.js', done);
}
else {
done();
}
}
else {
event.theme = 'ruby';
event.heading = '<i class=\'fa fa-warning\'></i> Process Failure';
event.message = 'User could not create.';
event.sticky = true;
$("#divfailed").empty();
$("#divfailed").hide();
$("#divfailed").append("<i class='fa fa-warning'></i> " + data.ErrorMessage);
$("#divfailed").show(500);
setTimeout(function () {
$("#divfailed").hide(500);
}, 3000);
}
},
error: function (a, b, c) {
debugger
event.theme = 'ruby';
event.heading = '<i class=\'fa fa-warning\'></i> Process Failure';
event.message = 'Object could not create.';
$("#divfailed").empty();
$("#divfailed").hide();
msg = c !== "" ? c : a.responseText;
$("#divfailed").append("<i class='fa fa-warning'></i> " + msg);
$("#divfailed").show(500);
setTimeout(function () {
$("#divfailed").hide(500);
}, 3000);
}
});
i want to iterate over a json array of arrays from th controller i want to know how i could iterate over it
i need help: nay could help me i'm new to json and mvc
//server code
var jsonData = new
{
rows =
(from bathymetrie in bathymetries
select new
{
count = bathymetries.Count,
Id = bathymetrie.Id,
date = (bathymetrie.displayedDate != null) ?
bathymetrie.displayedDate.ToString() : ""
}).ToArray()
};
//client code
success: function (data) {
bathyms = "{";
for (var i = 0; i < data[1].count; i++) {
bathyms += el[i].Id + " : " + el[i].date;
alert(el[i].Id);
alert(el[i].date);
console.log(el[i].date);
if (i != data[0].count) {
bathyms += ",";
}
}
bathyms += "}";
}
Your data is an object with single field row, which contains an array of objects. Thus, iteration should look like this:
for (var i = 0; i < data.rows.length; i++) {
var element = data.rows[i];
// use element.Id, element.count and element.date
Say if you have your model like this -
public class Data
{
public int Id { get; set; }
public int Count { get; set; }
public string Date { get; set; }
}
And you are returning JsonResult of Array object like this -
public ActionResult GetJson()
{
Data[] a = new Data[2];
a[0] = new Data() { Count = 10, Id = 1, Date = "2/19/2014" };
a[1] = new Data() { Count = 20, Id = 2, Date = "3/19/2014" };
return new JsonResult() { Data = a };
}
Then you can invoke this action in JQuery in the following way -
<script src="~/Scripts/jquery-1.10.2.min.js"></script>
<script>
function submitForm() {
jQuery.ajax({
type: "POST",
url: "#Url.Action("GetJson")",
dataType: "json",
contentType: "application/json; charset=utf-8",
success: function (data) {
$.each(data, function (key, value) {
alert(value.Id + ' ' + value.Count + ' ' + value.Date);
});
},
failure: function (errMsg) {
alert(errMsg);
}
});
}
</script>
<input type="button" value="Click" onclick="submitForm()" />
Please observe following code which will iterate array -
success: function (data) {
$.each(data, function (key, value) {
alert(value.Id + ' ' + value.Count + ' ' + value.Date);
});
Output would be N number of alerts based on N elements in array like below -
how can fill a grid with kendo.....
This is my controller
it`s work
public JsonResult listarporfecha([DataSourceRequest] DataSourceRequest request, string anio, string mes)
{
List<Reporte1Hist> reporte = new List<Reporte1Hist>();
DateTime fecha;
DateTime time;
short dia = 31;
short year = Convert.ToInt16(anio);
short m = Convert.ToInt16(mes);
// string date = anio + "-" + mes + "-" + dia;
DateTime fdate;
string MyString;
try
{
if (mes == null && anio == null)
{
fecha = DateTime.Now;
}
else
{
time = new DateTime(year, m, dia);
reporte = contexto.Reporte1Hist.Where(p => p.Fecha == time).ToList();
}
}
catch (Exception)
{
throw;
}
return Json(new[] { reporte }.ToDataSourceResult(request, ModelState));
}
and this is my jquery, it doesn't work,
var url = '#Url.Action("listarporfecha","Home")';
$.post(url, { anio: year, mes: month }, function (data) {
$("#Grid").kendoGrid({
dataSource: {
transport: {
read: {
type:"POST",
url: '#Url.Action("listarporfecha","Home")',
dataType: "json",
data:data
}
}
// schema: {
// data: "data"
//}
}
});
});