Cannot get an element in an EditorTemplate - javascript

The following EditorTemplate does not work how I would like;
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<SHP.Models.BusinessUnitSelected>" %>
<tr>
<td><%: Model.BusinessUnit.BusinessUnitName %></td>
<td><%: Html.CheckBoxFor(model => model.Selected,
new { onclick = "SaveSelection(" + Model.EmployeeId + ", " + Model.BusinessUnit.BusinessUnitId + ", " + Convert.ToInt32(Model.Selected) + ", " + this.ClientID + ")" }) %>
</td>
</tr>
I want to get the Id of the Checkbox, and this.ClientID fails to do that.
This EditorTemplate forms a grid of rows within a table.
When a person clicks on the checkbox, the SaveSelection javascript is performed;
function SaveSelection(employeeId, businessUnitId, selectedFlag, elementId) {
//var tempFlag = selectedFlag === "0";
var element = document.getElementById(elementId);
if (selectedFlag === null) {
selectedFlag = true;
} else {
selectedFlag = !selectedFlag;
}
var url = '<%: Url.Action("AddBusinessUnitForEmployee", "DataService")%>';
dataService.saveSelection(employeeId, businessUnitId, selectedFlag, elementId, SavedSetting, url);
}
SavedSetting = function(data) {
$('#' + data.ElementId).after('<span class="error">' + data.Message + '</span>');
};
What I want is to display a message next to the checkbox after the server call.
So how do I do this?
Upticks will be awarded for advice on how I can improve this code.

You could use HTML5 data-* attributes:
<%# Control
Language="C#"
Inherits="System.Web.Mvc.ViewUserControl<SHP.Models.BusinessUnitSelected>"
%>
<tr>
<td><%: Model.BusinessUnit.BusinessUnitName %></td>
<td>
<%= Html.CheckBoxFor(
x => x.Selected,
new {
data_url = Url.Action("AddBusinessUnitForEmployee", "DataService"),
data_employeeId = Model.EmployeeId,
data_businessUnitId = Model.BusinessUnit.BusinessUnitId
}
) %>
</td>
</tr>
and then in a separate javascript file unobtrusively subscribe to the .click() event of those checkboxes and then fetch the required information from the data-* attributes:
$(function() {
$('tr input[type="checkbox"]').click(function() {
var elementId = $(this).attr('id');
var url = $(this).data('url');
var employeeId = $(this).data('employeeId');
var businessUnitId = $(this).data('businessUnitId');
var selectedFlag = !$(this).is(':checked');
dataService.saveSelection(
employeeId,
businessUnitId,
selectedFlag,
elementId,
SavedSetting,
url
);
});
});
Remark: I can't exactly remember if ASP.NET MVC 2 supported the data_ syntax in order to rewrite it to data- syntax in the generated markup. This is defintely supported in ASP.NET MVC 3 and later. If it doesn't work for you, you could use a different overload taking a RouteValueDictionary:
<%= Html.CheckBoxFor(
x => x.Selected,
new RouteValueDictionary
{
{ "data-url", Url.Action("AddBusinessUnitForEmployee", "DataService") },
{ "data-employeeId", Model.EmployeeId },
{ "data-businessUnitId", Model.BusinessUnit.BusinessUnitId }
}
) %>

Related

Get all cards from Trello and store details

I'm trying to write some simple Javascript that uses the Trello API to get all boards / lists / cards from my account and add them into an sortable table (using the Datatables jquery plugin).
I've so far managed to write a jsfiddle that gets all this information and writes it to a page, but I can't work out how to store all this information into some sort of data structure that can then be passed to the datatable plugin.
This is the fiddle I have so far that gets the data from Trello:
JS Fiddle Link
var carddata = [];
Trello.members.get("me", function(member) {
$("#fullName").text(member.fullName);
var boardUrl = "";
boardUrl = "members/me/boards";
Trello.get(boardUrl, function(boards) {
$.each(boards, function(ix, board) {
Trello.get("/boards/" + board.id + "/lists", function(lists) {
$.each(lists, function(ix, list) {
Trello.get("lists/" + list.id + "/cards", function(cards) {
$.each(cards, function(ix, card) {
console.log("boardname: " + board.name + "; list name: " + list.name + "; card name: " + card.name);
carddata.push(
"boardname: " + board.name +
"; list name: " + list.name +
"; card name: " + card.name
);
var $tablerow = "";
$tablerow = $(
"<tr><td>" + board.name +
"</td><td>" + list.name +
"</td><td>" + card.name +
"</td></tr>"
).appendTo("#table_body");
});
/*
for (i = 0; i < carddata.length; i++) {
console.log("carddata: " + carddata[i]);
}
*/
});
});
});
});
});
});
// **** carddata array is empty at this point ****
for (i = 0; i < carddata.length; i++) {
console.log("carddata: " + carddata[i]);
}
It loops through all boards, lists and cards and currently adds what it finds to a html table (and also an array). I then use the Datatables plugin to change that HTML table into a sortable table.
However the plugin is seeing the HTML table as empty (from what I can see), I presume this is because of something like the plugin code being called before the Javascript builds up the table in HTML.
So instead I planned to add all the data into an array, and then pass that array into the datatable as a datasource, but I can 't see how to make the array accessible outside the very inner loop. From doing some searches I think this is to do with closures and scope but I'm struggling to understand how they work (I'm very new to Javascript).
Is anyone able to help me get this basic code working and show me what I'm doing wrong?
Thanks,
David.
The following code snippet demonstrate how to add data to data table after table created. For how to wait for all asyn requests completed, setTimeout is used to simulate Trello.get method for the asyn behavior.
var boardHash = {};
var listHash = {};
var updateLoggedIn = function() {
$("#loggedout").toggle(!isLoggedIn);
$("#loggedin").toggle(isLoggedIn);
};
var loadCardData = function(){
var carddata = [];
var loadMember = function() {
setTimeout(function(){
console.log("Member loaded");
loadBoard();
},2000);
}
var loadBoard = function() {
setTimeout(function(){
console.log("Boards loaded");
var listPromises = [];
loadList(["boardA","boardB","boardC"],listPromises);
$.when.apply($, listPromises).then(function(){
table.rows.add(carddata).draw("");
});
},1000);
};
var loadList = function(boards,listPromises){
$.each(boards,function(boardIndex, boardValue){
var listDefered = $.Deferred();
listPromises.push(listDefered.promise());
setTimeout(function(){
console.log(boardValue+" lists loaded");
var cardPromises = [];
loadCard(["listA","listA","listC"],boardValue,cardPromises);
$.when.apply($, cardPromises).then(function(){
listDefered.resolve();
});
},(boardIndex+1)*900);
});
};
var loadCard = function(lists,boardValue,cardPromises){
$.each(["listA","listA","listC"],function(listIndex, listValue){
var cardDefered = $.Deferred();
cardPromises.push(cardDefered.promise());
setTimeout(function(){
console.log(boardValue+" "+listValue+" cards loaded");
$.each(["cardA","cardB","cardC"],function(cardIndex, cardValue){
carddata.push({
"boardName":boardValue,
"listName":listValue,
"cardName":cardValue
});
});
cardDefered.resolve();
},(listIndex+1)*800);
});
};
loadMember();
};
var logout = function() {
updateLoggedIn();
};
$("#connectLink")
.click(function() {
loadCardData();
});
$("#disconnect").click(logout);
var consoleLine = "<p class=\"console-line\"></p>";
console = {
log: function(text) {
$("#console-log").append($(consoleLine).html(text));
}
};
var table = null;
$(document).ready( function () {
table = $('#table_id').DataTable({
columns: [
{ data: 'boardName' },
{ data: 'listName' },
{ data: 'cardName' }
]
});
} );
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<link href="//cdn.datatables.net/1.10.19/css/jquery.dataTables.min.css" rel="stylesheet" />
<script src="//cdn.datatables.net/1.10.19/js/jquery.dataTables.min.js"></script>
<div id="loggedout">
<a id="connectLink" href="#">Connect To Trello</a>
</div>
</head>
<div id="loggedin">
<div id="header">
Logged in to as <span id="fullName"></span>
<a id="disconnect" href="#">Log Out</a>
</div>
<div id="output"></div>
</div>
<table id="table_id" class="display" border=1>
<thead>
<tr>
<th>Board</th>
<th>List</th>
<th>Card</th>
</tr>
</thead>
<tbody id="table_body">
</tbody>
</table>
<div id="console-log"></div>
</html>
For adding data to data table
So in your code, add the columns options to the data table, and use rows.add method to add data to data table when all ajax request are done.
Wait for all ajax request completed
The most tricky part is how to ensure all response are done, this can be achieved by $.Deferred() and $.when.apply, see JQuery document and What does $.when.apply($, someArray) do? for more details.

Notify.js with rails

I have a simple notification template. I just want to apply a notification alert in my page. Not for button click, I need to show it after sign in / sign out events like that. I found a library which is very simple. Here is the link
I used it's styles and load it. It display correctly but jquery functions are not working. Here is my code for template
<% if !flash.nil? %>
<div class="alert-wrapper">
<% flash.each do |name, msg| %>
<div id="notifications" class="alert alert-success alert-<%= name %>" role="alert"><%= msg %></div>
<% end %>
</div>
<% end %>
JS file
$( document ).ready(function() {
Notify = function(text, callback, close_callback, style) {
var time = '10000';
var $container = $('#notifications');
var icon = '<i class="fa fa-info-circle "></i>';
if (typeof style == 'undefined' ) style = 'warning'
var html = $('<div class="alert alert-' + style + ' hide">' + icon + " " + text + '</div>');
$('<a>',{
text: '×',
class: 'button close',
style: 'padding-left: 10px;',
href: '#',
click: function(e){
e.preventDefault()
close_callback && close_callback()
remove_notice()
}
}).prependTo(html)
$container.prepend(html)
html.removeClass('hide').hide().fadeIn('slow')
function remove_notice() {
html.stop().fadeOut('slow').remove()
}
var timer = setInterval(remove_notice, time);
$(html).hover(function(){
clearInterval(timer);
}, function(){
timer = setInterval(remove_notice, time);
});
html.on('click', function () {
clearInterval(timer)
callback && callback()
remove_notice()
});
}
});
What am I missing here?

Grails non null params reaching controller as null?

I am having some trouble trying to get params from my GSP to my controller from a Javascript click handler that looks like this:
$('#save').click(function () {
var uniqueId = "${recordToEdit.uniqueId}";
var secondaryId = "${recordToEdit.secondaryId}";
console.log(removedYellowIssues);
<g:remoteFunction controller="customer"
action="saveModifiedIndividualRecord"
params='{uniqueId: uniqueId,
secondaryId: secondaryId,
yellowIssuesRemoved: removedYellowIssues,
redIssuesRemoved: removedRedIssues}'/>
});
When the "save" button is pressed this is what I see in the javascript console:
["No address provided."]
so you can see the the 'removedYellowIssues' list is NOT empty. It's a Javascript list containing one string. However, here is what my controller thinks:
<><><> Parameters ***:
<><><> uniqueId: 239400B
<><><> secondaryId: 1
<><><> Red issues removed: null
<><><> Yellow issues removed: null
Here is the controller action:
def saveModifiedIndividualRecord() {
println "<><><> Parameters ***: "
println "<><><> uniqueId: " + params.uniqueId
println "<><><> secondaryId: " + params.secondaryId
println "<><><> Red issues removed: " + params.redIssuesRemoved
println "<><><> Yellow issues removed: " + params.yellowIssuesRemoved
}
Here is more of the Javascript code containing the above save button snippet.
var currentYellowIndex = 0;
var allYellowIssues = $('#allYellowIssues'); // The unordered list 'ul'
var removedYellowIssues = []; // An array to keep track of issues removed
if (allYellowIssues.length) { // If there are issues to be displayed
var yellowElements = document.getElementsByName('yellowIssue');
var yellowListSize = yellowElements.length;
yellowElements[currentYellowIndex].className = "display";
$('#yellowStartIndex').html(currentYellowIndex + 1);
$('#yellowSizeIndex').html(yellowListSize);
$('#nextYellowIssue').click(function () {
if (currentYellowIndex < yellowListSize-1) {
yellowElements[currentYellowIndex++].className = "display-none";
yellowElements[currentYellowIndex].className = "display";
$('#yellowStartIndex').html(currentYellowIndex + 1);
}
});
$('#previousYellowIssue').click(function () {
if (currentYellowIndex > 0) {
yellowElements[currentYellowIndex--].className = "display-none";
yellowElements[currentYellowIndex].className = "display";
$('#yellowStartIndex').html(currentYellowIndex + 1);
}
});
$('#clearYellowFlag').click(function () {
removedYellowIssues.push(yellowElements[currentYellowIndex].innerHTML);
yellowElements[currentYellowIndex].className = "display-none";
yellowElements[currentYellowIndex].remove();
yellowListSize = yellowElements.length;
if (yellowListSize == 0)
$('#yellowIssues').hide();
else {
currentYellowIndex = 0;
yellowElements[currentYellowIndex].className = "display";
$('#yellowStartIndex').html(currentYellowIndex + 1);
$('#yellowSizeIndex').html(yellowListSize);
}
});
}
$('#save').click(function () {
var uniqueId = "${recordToEdit.uniqueId}";
var secondaryId = "${recordToEdit.secondaryId}";
console.log(removedYellowIssues);
<g:remoteFunction controller="customer"
action="saveModifiedIndividualRecord"
params='{uniqueId: uniqueId,
secondaryId: secondaryId,
yellowIssuesRemoved: removedYellowIssues,
redIssuesRemoved: removedRedIssues}'/>
});
The last part of the GSP is where the save button itself is defined as follows:
<br>
<button id="save"> Save </button>&nbsp&nbsp&nbsp
<button id="cancel" class="close" type="button"> Cancel </button>
I feel like the { } in the params should be [ ] instead. The g:remoteFunction is a GSP tag and the params should be a map.
<g:remoteFunction controller="customer"
action="saveModifiedIndividualRecord"
params='[uniqueId: uniqueId,
secondaryId: secondaryId,
yellowIssuesRemoved: removedYellowIssues,
redIssuesRemoved: removedRedIssues]'/>
However, you really shouldn't use that tag (I think it is deprecated in the latest versions). You should just do an a post via jQuery:
$.post("${g.createLink(action: 'saveModifiedIndividualRecord')", {uniqueId: uniqueId, ...}, function(result) {
...
});

Get the selected option/value of a dynamic select field in RAILS

I have here a select_field with a dynamic ID.
Why dynamic? Because I used a nested field/form.
<%= f.select :category_id, Category.all.map{ |c| [c.code, c.id] }, {prompt:""},{class:"cat-code"} %>
I have here a JS code that simply gets the dynamic id per select field.
<%= javascript_tag do %>
$(function() {
$(".cat-code").change(function(){
var getID = this.id;
var value = $("getID").val()
alert(value);
if (value == "1"){
$(".div1").show();
$(".div2").hide();
}
else if (value == "2"){
$(".div1").hide();
$(".div2").show();
}
});
});
<% end %>
I can get the id using..
alert(getID);
But getting the selected value turns undefined which results the show() and hide() divs for not working too.
Any workarounds will be appreciated. Thanks.
var value = $("#" + getID).val()
var element = $(this);
var value = element.val()
Thank you guys, already solved this using.
$(".cat-code").change(function(){
var getID = this.id;
var value = document.getElementById(this.id).value;
console.log(getID + "with a value of" + value);
if (value == ){
$(".div1").show();
$(".div2").hide();
}
else if (value == "2"){
$(".div1").hide();
$(".div2").show();
}
});

Html.Textbox value is not passing in url using javascript

I`m trying to pass the Html.Textbox value in the javascript url but it is giving an error.
Server Error in '/' Application.
The resource cannot be found.
Description: HTTP 404. The resource you are looking for (or one of its dependencies) could have been removed, had its name changed, or is temporarily unavailable. Please review the following URL and make sure that it is spelled correctly.
Requested URL: /WebProduct/Add/1
Below is my view class. from which i`m passing values to my controller.
Edited
#model IEnumerable<DatabaseService_WebAPI.Models.ProductType>
#{
ViewBag.Title = "Tablets";
<script type="text/javascript">
$(function () {
$('#edit').click(function () {
var name = $('#quantity').val();
this.href = this.href + '&quantity=' + encodeURIComponent(name);
});
});
</script>
}
<h2>Tablets</h2>
#using (Html.BeginForm("Add", "WebProduct", FormMethod.Post))
{
#Html.ValidationSummary(true)
<table>
<tr>
<th>
#Html.DisplayNameFor(model => model.Name)
</th>
<th>
#Html.DisplayNameFor(model => model.Price)
</th>
<th>
#Html.DisplayNameFor(model => model.Batch)
</th>
<th>
#Html.DisplayNameFor(model => model.Expiry)
</th>
<th>
#Html.DisplayNameFor(model => model.Quantity)
</th>
</tr>
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.Name)
</td>
<td>
#Html.DisplayFor(modelItem => item.Price)
</td>
<td>
#Html.DisplayFor(modelItem => item.Batch)
</td>
<td>
#Html.DisplayFor(modelItem => item.Expiry)
</td>
<td>
#Html.TextBox("quantity")
</td>
<td>
#Html.ActionLink("Add", "Add", new { name = item.Name, type = item.Type }, new { id = "edit" })
</td>
</tr>
}
</table>
}
<div>
#Html.ActionLink("Back to List", "Create")
</div>
And its my controller method in which I`m passing the values.
[HttpPost]
public ActionResult Add(string quantity, string name, string type)
{
Product product = new Product();
if (type=="Tablet")
{
//string order = type.Name + " " + type.Quantity;
LocalDB tobj = ldb.LocalDBs.Single(s => s.User == User.Identity.Name);
product.city = tobj.City;
product.OrderDate = DateTime.Now.Date.ToShortDateString();
product.ShopName = tobj.ShopName;
product.User = tobj.User;
//product.OrderDetail = order;
db.Products.Add(product);
db.SaveChanges();
return RedirectToAction("TypeT", "WebProduct");
}
else if (type == "Syrup")
{
//string order = type.Name + " " + type.Quantity;
LocalDB tobj = ldb.LocalDBs.Single(s => s.User == User.Identity.Name);
product.city = tobj.City;
product.OrderDate = DateTime.Now.Date.ToShortDateString();
product.ShopName = tobj.ShopName;
product.User = tobj.User;
// product.OrderDetail = order;
db.Products.Add(product);
db.SaveChanges();
return RedirectToAction("TypeS", "WebProduct");
}
else
{
// string order = type.Name + " " + type.Quantity;
LocalDB tobj = ldb.LocalDBs.Single(s => s.User == User.Identity.Name);
product.city = tobj.City;
product.OrderDate = DateTime.Now.Date.ToShortDateString();
product.ShopName = tobj.ShopName;
product.User = tobj.User;
// product.OrderDetail = order;
db.Products.Add(product);
db.SaveChanges();
return RedirectToAction("TypeC", "WebProduct");
}
return View();
}
At this point i don't want to use button options. because i want to send database record and user's input to my controller`s method.
My understanding is that your
this.href == localhost:3325/WebProduct/Add?name=Panadol&type=Tablet
if that is correct then the following should work
$(function ()
{
$('#edit').click(function ()
{
var name = $('#quantity').val();
var href = this.href;
var splitHalfUrl = href.split('?');
var splitQueryString = splitHalfUrl[1].split('&');
window.location = "/WebProduct/Add?" + "quantity=" + encodeURIComponent(name) // Quantity
"&" + splitQueryString[0] + // Name
"&" + splitQueryString[1]; // Type
});
});
Ok couple things I'd like to point out, you need to prevent default behavior on the ActionLink:
<script type="text/javascript">
$(function () {
$('#edit').click(function(event) {
event.preventDefault();
var name = $('#quantity').val();
window.location = this.href + '&quantity=' + encodeURIComponent(name);
});
});
</script>
That should redirect your page to the url that you want: localhost:port/WebProduct/Add?name=Name&type=Type&quantity=Quantity
If you get another error, please check if your controller action is setup properly (spelling mistake can be a bitch).
The line
this.href = this.href + '?quantity=' + encodeURIComponent(name);
your url will read something like
http://localhost:54745/WebProduct/Add?id=1&name=myname&type=mytype?quantity=4
two question marks can't be in the same url query string like this
UPDATE:
Your also in a foreach loop, meaning you will have multiple textboxes with id 'quantity' and multiple add links with id 'edit'
UPDATE 2:
add the parameter 'e' on the click event in order to call 'e.preventDefault()' this will stop the link from going to its URL.
then you will also need to set the window.location, rather than this.href (which is the link URL)
$(function () {
$('#edit').click(function (e) {
e.preventDefault();
var name = $('#quantity').val();
window.location = this.href + '&quantity=' + encodeURIComponent(name);
});
});
</script>

Categories

Resources