I have a view with a modal pop-up that displays "parameters" or rather data from a Dictionary being passed to the front end. With my current JS, it appears my function will only deserializing one key and value at a time. However, I need to edit the function so that It can deserialize more than one key and value, if the dictionary is passing in more than one key and value..
Below is my code. If you want to know more about the back end please let me know.
Controller is returning:
var parameters = new Dictionary<string, string>();
return Json(parameters, JsonRequestBehavior.AllowGet);
To reiterate, parameters is a Dictionary that can have either one key/value OR it could hold multiple key/value pairs.
JS:
$("button[name='paramsBtn']").click(function () {
/* Grabs ID from col selected */
var $col = $(this).closest('.row').find('.requestId');
var jobRequestId = $col.data('id');
$.ajax({
url: '#Url.Action("JobPollerParameters", "Tools")',
data: { "jobRequestId": jobRequestId},
success: function (results) {
$modal = $('#paramsModal');
$modal.modal("show");
var arr = results;
//loop through arr created from dictionary to grab key(s)
for (var key in arr) {
if (arr.hasOwnProperty(key)) {
var myKey = key;
}
}
var name = myKey;
var value = results[myKey];
$('#modalName').text(name);
$('#modalMessage').text(value);
}
});
});
Here is the modal:
<div class="modal fade" id="paramsModal" tabindex="-1" role="dialog">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header modal-header-primary">
<a class="btn btn-xs btn-primary pull-right" data-dismiss="modal" aria-label="Close"><span class="glyphicon glyphicon-remove"></span></a>
<h4 class="modal-title" id="modalTitleText">Job Parameters</h4>
</div>
<div class="modal-body">
<div class="list-group">
<div class="row list-group-item list-group-item-heading container divTableHeading" style="width:inherit; margin-bottom:0px;">
<div class="col-md-6 font-weight-bold"> Parameter: </div>
<div class="col-md-6 font-weight-bold"> Value: </div>
</div>
<div class="row list-group-item container" style="width:inherit;">
<div class="col-md-6 text-break" id="modalName"></div>
<div class="col-md-6 text-break" id="modalMessage"></div>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
This line is confusing:
var myKey = key;
After the loop completes, myKey will be equal to the last index in your array, so 2 if results had length 3.
So, name will equal 2 and value will be equal to the last element in results
Maybe you're looking for something like this, since results is {string, string}:
// sample results array from server
var arr = ["val1", "val2", "val3"];
var displayString = "";
for (var key in arr) {
if (arr.hasOwnProperty(key)) {
displayString += arr[key] + ","; // note, there will be a trailing comma
}
}
console.log(displayString);
See the comments below, essentially you arent doing all of the work inside the loop thus your function appears to produce 1 variable (the last one in the dictionary)
$("button[name='paramsBtn']").click(function () {
/* Grabs ID from col selected */
var $col = $(this).closest('.row').find('.requestId');
var jobRequestId = $col.data('id');
$.ajax({
url: '#Url.Action("JobPollerParameters", "Tools")',
data: { "jobRequestId": jobRequestId},
success: function (results) {
$modal = $('#paramsModal');
$modal.modal("show");
var arr = results;
//loop through arr created from dictionary to grab key(s)
for (var key in arr) {
if (arr.hasOwnProperty(key)) {
var myKey = key;
}
}
//Move these variables inside the loop. you are setting them once
//they are in essence being set to the last value in the dictionary
var name = myKey;
var value = results[myKey];
$('#modalName').text(name);
$('#modalMessage').text(value);
}
});
});
Related
I have some code that retrieves users from a server (ajax) and I use some <a> tags to display it, and when you click on an <a> tag with a user, it's supposed to add it to an array in_group. The first one works, the second one goes to the alert() function AND also adds the user to the array, which confuses me. The remove button doesn't work either. What am I doing wrong? I want the user to be added to the in_group array only if doesn't exist, and to be deleted when the button is pressed.
var in_group = [];
$("#students-body").on('click', 'a', function() {
var modal = $("#manageGroupMembers");
var student_id = $(this).attr('student-id');
var student_name = $(this).html();
var student = {
id: student_id,
name: student_name
};
console.log(in_group.length);
if (in_group.length > 0)
{
for (i = 0; i < in_group.length; i++)
{
console.log(in_group[i].id);
if (in_group[i].id === student_id)
{
alert('in grp');
return;
}
else
{
in_group.push(student);
}
}
}
else
{
in_group.push(student);
}
RefreshGroup();
//modal.modal('hide');
});
function RefreshGroup()
{
var students_group = $("#students-group");
var html = "";
if (in_group.length > 0)
{
for (i = 0; i < in_group.length; i++)
{
html += "<span>"+in_group[i].name+"</span>";
html += "<button class='btn btn-danger' onclick='event.preventDefault();RemoveFromGroup("+i+")'>x</button>";
}
students_group.append(html);
}
}
function RemoveFromGroup(index) {
in_group.splice(index, 1);
RefreshGroup();
}
Html:
<div class="form-group">
<label for="group_members">Members</label>
<button class="btn btn-primary" style="display: block;" onclick="event.preventDefault()" id="add-student-btn">Add Member</button>
<div id="students-group"></div>
</div>
Modal:
<!-- Modal -->
<div class="modal fade" id="manageGroupMembers" role="dialog">
<div class="modal-dialog">
<!-- Modal content-->
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<h4 class="modal-title">Add Member to Group</h4>
</div>
<div class="modal-body">
<div id="students-body"></div>
<div id="pagination-students"></div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
That's because you are inserting the id in a for loop. Change your code:
...your code before this....
var student_id = $(this).attr('student-id');
var student_name = $(this).html();
var student = {
id: student_id,
name: student_name
};
var index = in_group.findIndex(function(std) {
return std.id == student.id;
});
if(index === -1) {
in_group.push(student);
} else {
alert('student was already in array')
}
This way, you check if the student is inside the array. If not (-1) you insert it. Else you alert
In this section of your code, you’re looping the in_group array to find a student entry with a specific ID.
if (in_group.length > 0)
{
for (i = 0; i < in_group.length; i++)
{
console.log(in_group[i].id);
if (in_group[i].id === student_id)
{
alert('in grp');
return;
}
else
{
in_group.push(student);
}
}
}
else
{
in_group.push(student);
}
RefreshGroup();
If you find it, you alert it, and then you stop the loop and the entire function. If you don’t find it, you push it, but you don’t break the loop. You keep looping, the check in_group[i].id === student_id is re-executed and the alert is executed as well.
You could add a return; after calling RefreshGroup, however, why not get rid of the loops and make things easier?
let isInGroup = in_group.find(studentEntry => studentEntry.id === student_id);
if(isInGroup){
alert("in grp");
}
else{
in_group.push(student);
RefreshGroup();
}
This will replace the above section completely and it will work.
As to why the removal doesn’t work:
event isn’t defined. It’ll likely produce a ReferenceError. (Same problem for your other <button>.)
Instead of inline event attributes, look into event delegation and standard event listeners (jQuery has the click method—use it!)
Look into data- attributes or jQuery’s data to hold the value of the index.
Event delegation could look like this:
var students_group = $("#students-group");
students_group.on("click", "button", function(e){
RemoveFromGroup($(this).attr("data-index"));
});
And then, when generating the HTML:
html += "<button class='btn btn-danger' data-index='" + i + "'>x</button>";
I’d also recommend reading about Array.prototype methods, particularly the iteration methods.
my model code
public class viewCase
{
public List<string> lstCategory { get; set; }
public DataTable dtWrkTsk { get; set; }
}
my controller code
string query = "SELECT WorkFlowID,Subject,Category FROM CMSTasksWorkFlow"
objcase.dtWrkTsk = objdataclas.ExecuteDataTable(query);
return View("../ViewCases/CasesScreen",objcase);
my cshtml code
function getCaption() {
var cat= $("#layout option:selected").text(); //variable for select condition
var arr = #Html.Raw(Newtonsoft.Json.JsonConvert.SerializeObject(
Model.dtWrkTsk.Select("Catagory='" + cat + "'") )); //<- error here
}
its giving me error 'cat ' does not exist in current context
and if i try
function getCaption() {
var cat= $("#layout option:selected").text(); //variable for select condition
var arr = #Html.Raw(Newtonsoft.Json.JsonConvert.SerializeObject(
Model.dtWrkTsk.Select("Catagory='" +#<text> cat </text> + "'") ));} //<- error here
CS1660: Cannot convert lambda expression to type 'string' because it
is not a delegate type
<div id="addTask" class="modal fade " aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content round">
<div class="modal-header"><h4>New Task </h4></div>
<div id="tbody" class="modal-body" style="height:20%">
#Html.DropDownList("layout", Model.lstCategory.Select(m => new SelectListItem { Text = m, Value = m }), "All", new { onclick = "getCaption()" })
<div id="dtask" style="width: 80%; overflow: scroll; ">
</div>
</div>
<div class="modal-footer">
<button type="button" data-dismiss="modal" class="btn btn-primary" >OK</button>
<button type="button" data-dismiss="modal" class="btn">Cancel</button>
</div>
</div>
</div>
</div>
i am trying to keep datatable disconnected from server so whenever user changes value in Html.DropDownList function getCaption() is called
i only need select condition in datatable where i select category with javascript varible passing
how do i pass my javascript variable in datatable.select
The #Html.Raw() in var arr = #Html.Raw(...) is razor code which is parsed on the server before its sent to the view. It includes a .Select() query that uses a javascript variable which does not exist at that point - its not in scope.
You need to assign the collection to a javascript variable, and the filter the resulting array in javascript based on the selected option.
The following assumes dtWrkTsk is a collection of a model containing a property string Category, and you want to filer the collection to return only objects whose Category value matches the selected option
#Html.DropDownList("layout", Model.lstCategory.Select(m => new SelectListItem { Text = m, Value = m }), "All")
or
#Html.DropDownList("layout", new SelectList(Model.lstCategory), "All")
<script>
// Assign the collection to a javascript array
var arr = #Html.Raw(Json.Encode(Model.dtWrkTsk))
$('#layout').change(function() {
var selectedCategory = $(this).val();
// Return all objects in the collection that match
var result = $(arr).filter(function(index, item) {
return item.Category === selectedCategory;
});
.... // do something with the results
});
</script>
Additional suggest reading - Unobtrusive JavaScript
I'm creating an array in a service and fetch some data from a db and iterative over the data to add the group id as a key in the array
angular.module('tasksApp').
factory("data", ["$http", function ($http) {
var data = {};
data.allTasks = {};
data.today = [];
data.actioned = [];
data.complete = [];
data.todaysNextNumber = 0;
data.groups = [];
data.groupNames = [];
data.nextGroupPosition = [];
data.loadTasks = function () {
return $http({
method: 'GET',
url: '/loadTasks'})
.then(function(response) {
data.allTasks = response.data;
// Get groups & create the arrays
getGroups().then(function(result) {
var allGroups = result;
for (var key in allGroups) {
var group = allGroups[key];
data.groups[group.group_id] = [];
data.groupNames[group.group_id] = group.group_name;
data.nextGroupPosition[group.group_id] = 0;
}
The id's of the data start with 1 and go up to 9.
Then, in the component I load the data to the scope:
angular.module('tasksApp').
component('tasks', {
templateUrl: 'tasks/template.tasks.html',
controller: function startUp($scope, $rootScope, data) {
// Get tasks
data.loadTasks().then(function(response) {
$scope.groups = data.groups;
$scope.today = data.today;
$scope.actioned = data.actioned;
$scope.groupNames = data.groupNames;
console.log($scope.groups);
})
}
});
and use ng-repeat to go over the data in the template:
<!-- Start of Groups -->
<div ng-repeat="(key, group) in groups" class="col-md-3">
<div class="groupBox">
<div ng-attr-id="{{'groupCell-' + key}}" ng-click="showTitleInput(key)">
<h1 ng-attr-id="{{'groupTitle-' + key}}">{{groupNames[key]}} - {{key}}</h1>
<input class="groupTitleInput" ng-attr-id="{{'groupInput-' + key}}" ng-value="groupNames[key]"></input></div>
<div ng-attr-id="{{'div' + key}}">
<div ng-repeat="task in group | orderBy:'position'" ng-attr-id="{{'task-' + task.id}}" class="taskContainer">
<div ng-attr-id="{{'taskText-' + task.id}}" class="taskText" ng-click="displayActionBar = !displayActionBar">{{task.task}}</div>
<div ng-attr-id="{{'actionBar-' + task.id}}" class="actionBar" ng-show="displayActionBar">
<div class="actionButton glyphicon glyphicon-globe todaysTasks" ng-click="displayActionBar = !displayActionBar; addToToday(task.id, task.group_id)"></div>
<div class="actionButton glyphicon glyphicon-ok actioned" ng-click="displayActionBar = !displayActionBar; markAsActioned(task.id, task.group_id)"></div>
<div class="actionButton glyphicon glyphicon-thumbs-up complete" ng-click="displayActionBar = !displayActionBar; markAsComplete(task.id, task.group_id)"></div>
<div class="actionButton glyphicon glyphicon-trash delete" ng-click="displayActionBar = !displayActionBar; deleteTask(task.id, task.group_id)"></div>
<div class="actionButton glyphicon glyphicon-remove cancel" ng-click="displayActionBar = !displayActionBar"></div>
<div class="actionButton glyphicon glyphicon-menu-up up" ng-click="pushUp(task.id, task.group_id)"></div>
<div class="actionButton glyphicon glyphicon-menu-down down" ng-click="pushDown(task.id, task.group_id)"></div></div></div></div>
<form ng-submit="addTask(key)" ><input name={{key}} class="newTaskInput" type="text" ng-model="newTaskDescription" /><form></div></div>
All this works fine but when the data is displayed a div for an '0' element is shown. If I print the array out using console.log it doesn't show a '0' element. Also, if I change the data with the id of 1 to 0 it also iterates over a 1 element. I thought that ng-repeat iterated over the elements in the array using the assigned key, not going from 0 through to the number of elements.
Does anyone know why this is happening?
I'm unable to push objects to an array and i can't figure out why. At the moment, the result (records) repeats the last instance of the each loop.
JSFiddle
HTML
<div data-provider="prv1"></div>
<div data-rating="rtn1"></div>
<div data-price="prc1"></div>
<div data-provider="prv2"></div>
<div data-rating="rtn2"></div>
<div data-price="prc2"></div>
<div data-provider="prv3"></div>
<div data-rating="rtn3"></div>
<div data-price="prc3"></div>
<div data-provider="prv4"></div>
<div data-rating="rtn4"></div>
<div data-price="prc4"></div>
Javascript (w/ jQuery)
(function(){
var sort = $(".sort select");
var provider = $("[data-provider]");
var rating = $("[data-rating]");
var price = $("[data-price]");
var records = [];
var record = {};
$(provider).each(function(index, value){
record.provider = $(provider).eq(index).data("provider");
record.rating = $(rating).eq(index).data("rating");
record.price = $(price).eq(index).data("price");
records[index] = record;
});
})();
In your loop you set each index to be equal to record. Since the scope of record is the anonymous function, it will be the same object for each index.
What you want is for the scope to be the function provided to .each
Like this fiddle
$(provider).each(function(index, value){
var record = {};
...
});
I have added a server side pagination with table sorter successfully. I just would like to know how can I refresh it? I would like to create a button to call a refresh function. Does anyone know if there is any method to do it? I do not want to reload the page for it.
UPDATE:
ajaxProcessing: function(data){
if (data && data.hasOwnProperty('rows')) {
var r, row, c, d = data.rows,
total = data.total_rows,
headers = data.headers,
rows = [],
len = d.length;
for ( r=0; r < len; r++ ) {
row = []; // new row array
// cells
for (c in d[r]) {
if (typeof(c) === "string") {
row.push(d[r][c]); //add each table cell data to row array
}
}
rows.push(row); // add new row array to rows array
}
var items="";
$("#tabelaTickets tr:has(td)").remove();
if (rows!==null && rows.length!== 0) {
$.each(rows,function(index,item) {
$("#tabelaTickets").append('<tr class="danger"><td align="center" style="width: 70px"><a type="button" class="btn btn-primary btn-xs" data-placement="right" title="Visualizar ticket" data-toggle="modal" class="btn btn-primary" href="visualizar.php?ticket='+item[3]+'"> #' + item[3] + '</a></td><td><div style="text-overflow:ellipsis;overflow:hidden;width:250px">' + item[4] + '</div></td><td><div style="text-overflow:ellipsis;overflow:hidden;width:350px;">' + item[5] + '</div></td><td><div style="text-overflow:ellipsis;overflow:hidden;width:250px;">' + item[6] + '</div></td><td><div style="text-overflow:ellipsis;overflow:hidden;width:60px;">' + item[7] + '</div></td><td><div style="text-overflow:ellipsis;overflow:hidden;width:70px;">' + item[8] + '</div></td></tr>');
});
}else{
$("#tabelaTickets").append('<tr><td colspan = "6" align="center">SEM RESULTADO A SER EXIBIDO</td></tr>');
}
$("#tabelaTickets").trigger("update");
$("#tabelaTickets").trigger("appendCache");
$("#pleaseWaitDialog").modal('hide');
// in version 2.10, you can optionally return $(rows) a set of table rows within a jQuery object
return [ total];
}
},
Thanks since now,
Erik
your repsonse is JSON, it's easy with a little AJAX function.
example your HTML is look like :
<div class="wrapper">
<div class="item">
<span>item 01</span>
</div>
<div class="item">
<span>item 02</span>
</div>
<div class="item">
<span>item 03 </span>
</div>
</div>
<button class="btn refresh-btn" type="submit"></button>
your response JSON maybe look like :
response = {
{ content : item11 },
{ content : item12 },
{ content : item13 }
};
your HTML render function with AJAX will be look like :
$('.refresh-btn').on('click', function() {
var url = 'yourUrl/?param=refresh&example=true';
var $wrapper = $('.wrapper'); // a div that wrap your new HTML.
$.get(url, {}) //call AJAX GET new item.
.done(function(data) {
$wrapper.html(''); // clear old list;
var $template = $('<div/>', {class : 'item'} ); // create item's HTML.
data.arrayItemList.forEach(function(item) {
var itemTemplate = $template.clone();
itemTemplate.append($('<span/>').text(item.content));
$wrapper.append(itemTemplate); // add new item in list.
});
});
})
that's mean : you create new HTML, and fill it with your data, everything worked fine.
Some time I create a empty template some where in view and clone it.
<div class="sample-template">
<div class="item">
<span> </span>
</div>
</div>
when I need it, I call the jQuery var $template = $('.sample-template').clone(); then fill data with $template.find('span').text(item.content);