mvc3 entity framework - convert comma separated list of strings into list<string> in viewmodel, allow users to remove items from list - json

I am struggling to figure out how to do this with MVC,
I have an entity framework object that has a comma separated list from the db, (can't change the fact that its a horrible csl in the db). I can easily display the list and let them edit it manually. This is rather error prone and would like to split them up and display a list of them in the view. Then allow the user to click a link / button and have them removed from the string and db and the page refreshed to reflect this.
My first thought was to use JQuery to do a ajax json post to do a delete for each item the click an #Html.ActionLink for. I could get it to do the async post back and it would delete the item and would send back a string representing the new string list which I could update the UL with. The second time they clicked a link it would give me a 404, the script I used is:
<script type="text/javascript">
$(document).ready(function () {
$('.viewSeasonsLink').click(function () {
var data =
{
item: $(this).parents('li').first().find('.flagName').text(),
deploymentId: #Model.Id
};
$.post(this.href, data, function (result) {
var list = $("#testme");
list.empty();
var items = result.split(",");
$(items).each(function(index) {
// /* var link = '"' + #Html.ActionLink("Remove", "RemoveItemFromList", "Deployment", null, new { #class = "viewSeasonsLink" }) + '"'; */
var link = '<a class="viewSeasonsLink" href="/SAMSite/Deployment/RemoveItemFromList">Remove</a>';
list.append('<li><span class="flagName">' + items[index] + '</span> - ' + link + ' </li>');
/* list.append('<li><span class="flagName">' + items[index] + '</span> - ' + '\'' + #Html.ActionLink("Remove", "RemoveItemFromList", "Deployment", null, new { #class = "viewSeasonsLink" }) + '\'</li>'); */
});
}, "json");
return false;
});
});
</script>
I could not get the action link to work with the jquery script, so tried hard coding it, still not success.
I then thought I would just try and do a simple actionlink back to a method to remove it and return the normal view, again this posts and will update the db, but will not refresh the webpage at all.
<ul id="testme2">
#foreach (string flag in ViewBag.FeatureFlags)
{
<li><span class="flagName">#flag</span> - #Html.ActionLink("Remove", "RemoveItemFromListTest", "Deployment", null, new { #class = "viewSeasonsLink" })</li>
}
</ul>
public ActionResult RemoveItemFromListTest(string item, int deploymentId)
{
Deployment deployment = db.Deployments.Single(d => d.Id == deploymentId);
ViewBag.CustomerId = new SelectList(db.Customers, "Id", "Name", deployment.CustomerId);
List<string> featureFlags = deployment.FeatureFlags.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList();
featureFlags.Remove(item);
deployment.FeatureFlags = ConvertBackToCommaList(featureFlags);
ViewBag.FeatureFlags = featureFlags;
//db.SaveChanges();
return View("Edit", deployment);
}
EDIT
released I was being a bit daft at one point:
The second test to get it to do a full post back and do the update was still getting caught by the jquery, (also was not passing in the values). I changed the line to this:
<li><span class="flagName">#flag</span> - #Html.ActionLink("Remove", "RemoveItemFromListTest", "Deployment", new { item = #flag, deploymentId = Model.Id }, null)</li>
which does work, but is a bit naff, it would mean any changes made to the form before the remove link clicked would be lost.

I think I see two issues. One is the initial .Post on the viewSeasonsList click event. You are posting back to the Action that loaded the page, not the Action that will handle the delete. I doesn't seem to me that they would be the same Action base on the approach you described.
var url = '/SAMSite/Deployment/RemoveItemFromList';
then
$.post(url, data, function (result) {
Second, in the Ajax response, when you are rebuilding the list, you are including an href attribute for the links. Why? you are not navigating with those links, you are initiating an Ajax request, which has already been set up.
var link = '<a class="viewSeasonsLink">Remove</a>';

ultimately I had one main problem with the jquery solution. When I added a new LI element it was not being hooked up to the ajax call as this was just happening at document.ready. I now replaced the simple .click with a delegate that will also hook up all elements that are added after the ready event, credit to this page for help with it:
$('#featureflaglist').delegate('.removeflaglink', 'click', RemoveFlagFromList);

Related

NetSuite Online HTML Form - link to list within NetSuite

I have an online html form that uses a select field to choose a record from an existing record list (postcodes specifically) which then auto-populates other fields on the form with the rest of the address. This all works fine except that the dropdown list on the form only goes up so far. I need to know if this a limit on the html dropdown or how many records can be passed to the list in the first place?
Also, ideally, it would be great if there was a way to do it via auto-complete so as you start typing the postcode, it only shows those beginning with said characters - is this possible?
I would set up a custom html template for your online form. You can then hide your standard field and include a custom text input field. Attach an event handler to the custom field to do the lookup via a suitelet. If the auto-population is already working then your event handler can update the hidden standard field once a match is made so Netsuite's built-in sourcing works.
A sample suitelet. The get... functions return anything that can be JSON used by your page.
function service(request, response) {
var obj = {
success: true
};
try {
var step = request.getParameter('step') || 'start';
switch (step) {
case 'start':
obj.choices = getChoiceRoots(request.getParameter('itemid'), request.getParameter('treeName'));
break;
case 'other':
obj.choices = getChoiceChildren(request.getParameterValues('choiceIds[]') || request.getParameterValues('choiceIds'));
break;
default:
throw "Unexpected step: " + step;
}
} catch (e) {
obj.success = false;
obj.message = e.message || e.toString();
nlapiLogExecution('ERROR', "error getting choices", (e.message || e.toString()) + "<br> " + request.getURL() + (e.getStackTrace ? "<br> " + e.getStackTrace().join("<br> ") : ''));
}
_sendJS(request, response, obj);
function _sendJS(request, response, respObject) {
response.setContentType('JAVASCRIPT'); //'application/json');
var callbackFcn = request.getParameter("jsoncallback") || request.getParameter('callback');
if (callbackFcn) {
response.writeLine(callbackFcn + "(" + JSON.stringify(respObject) + ");");
} else response.writeLine(JSON.stringify(respObject));
}
}
Then on your page you'd have a script that uses the suitelet. (the suitelet needs to be available without login and the audience needs to be All.
The code on your custom template or associated script file would look something like:
//suiteletURL will look like https://forms.netsuite.com. RegExp makes that root relative to the domain you are on.
//This is not actually necessary when using JSONP but it can be useful in some circumstances so I left it in this example.
$.getJSON(suiteletURL.replace(new RegExp(".*://[^/]+/"), '/')+"&"+$.param(params) +"&callback=?",
function(d, txtStatus,xhr){
if(d.errorCode){
if(fail){
fail(xhr, txtStatus, null);
}else{
showMessage("#appMessage", d.errorMessage || ("Request Failed with code: "+xhr.responseJSON.errorCode));
}
}else{
success(d, txtStatus, xhr); // your custom success handler. d is already an object; no parsing necessary.
}
});

dynamically get options of a dropdown menu in angular

The main problem is that I have a dropdown menu whose options should be updated dynamically.
The workflow is as follows:
I have an input element connected to an ng-model called toSubmit that when longer than 3 characters should fire an http.get call to fetch the list that should populate the dropdown menu.
So this list will change everytime the toSubmit variable changes. Let's call this list database (in the controller it is $scope.database.
What I am trying right now is a very simple solution that doesn't work most probably because the html DOM that contains the dropdown list is loaded at the very beginning and does not keep track of the changes in the options.
In my controller I have the following part which watches over toSubmit:
$scope.toSubmit = '';
$scope.$watch('toSubmit',function(query){
if (query.length >= 3){
getQueryDatabases.companyNameService({'field':'name','query':query,'numberOfHits':'10'},'CIK').prom.then(
function(dataObject){
$scope.database = dataObject;
// dataObject.forEach(function(item){
// $scope.databaseString.push(item.cik + ' ' + item.companyName);
});
});
}
});
And my html looks like the following:
<label for="nameCompany">Name:</label>
<input type="text" ng-model="toSubmit"></input>
<select ng-model="database" ng-options="line in database"></select>
Now my take was take by binding database with ng-Model I would get the result but I am most likely wrong. Can someone please help me?
I recommend you to use select2 that'll handle things like limiting input before server request and have great look and extendibility.
You need to add angular-ui-select2 to your project.
Here is code for you:
Html:
<input class='form-control' data-ng-model='position.company' data-ng-required data-placeholder='Company:' data-ui-select2='employerSelect2Options' id='company_name' type='hidden'>
JavaScript:
$scope.employerSelect2Options = {
minimumInputLength: 2,
query: function (query) {
var _query = query;
var companies = Restangular.all('companies').getList({query: query.term});
companies.then(function(data) {
var results = {results: []};
_.each(data, function(element, index, list) {
results.results.push({id: element.id, text: element.name});
})
if(!_.contains(_.map(data, function(element){ return element.name; }), _query.term)) {
results.results.push({id: _query.term , text: 'Create company "' + _query.term + '"'});
}
_query.callback(results);
})
}
};
My example also contains logic for add "create company" if zero results returned. In this case position.company will contain text of non found company name in id field and you can check it on server side and create one before assigning id.
This logic in
if(!_.contains
condition.

Getting Current Data from KendoUI TreeView

I'm using a kendo UI tree with a remote data source from a JSON file.
I have a button on the tree page which gets the current data of the tree,sends it through a POST to a server and the server saves the current data to the JSON file so as the next time I reload the page,the changes I made will be kept.That's what I want to happen.
So I know the current data of the tree is in:
$("#treeview").data("kendoTreeView").dataSource.data()
Which means the data changes real time in there for example when someone drag and drops a node of the tree.
My problem starts when this data doesn't seem to change when I drag and drop nodes inside the tree,and only changes when I drag and drop a node on the root level of the tree and even then it doesn't do it correcly as the node should be moved in there as well but instead the node gets copied,leaving the past node in the tree as well...
For Example I have this tree:
If I make a drag and drop change like this:
And I send the data,save it and reload the change isn't made at all!
PS:Even when I view the current data after the change before sending it,I see that there is no change on the data at all even though I did a change visualy with a drag and drop.So it doesn't have to do with the sending,saving and the server.
On the other hand,if I make a change like this:
I can see in the current data that the moved node is added in the end of the data indeed but it is not deleted from it's initial position within the data!So if i send the current data to the server,save it and then refresh I get the result:
The code for viewing and sending the data is:
function sendData() {
var req = createRequest();
var putUrl = "rest/hello/treeData";
req.open("post", putUrl, true);
req.setRequestHeader("Content-type","application/json");
var dsdata = $("#treeview").data("kendoTreeView").dataSource.data();
alert(JSON.stringify(dsdata));
req.send(JSON.stringify(dsdata));
req.onreadystatechange = function() {
if (req.readyState != 4) {
return;
}
if (req.status != 200) {
alert("Error: " + req.status);
return;
}
alert("Sent Data Status: " + req.responseText);
}
}
Is this a Bug or am I doing something wrong?Has anyone been able to see the current data changing correctly on every drag and drop?
First and most important you have to use the latest version of KendoUI (Kendo UI Beta v2012.3.1024) still in beta but is where they have solved many problems.
Then, when you create the kendoTreeView you have to say something like:
tree = $("#treeview").kendoTreeView({
dataSource :kendo.observableHierarchy(data),
dragAndDrop:true
}).data("kendoTreeView");
Here the important is not using directly data array but wrapping it with kendo.observableHierarchy.
Then you will have the data updated with the result of drag & drops.
For me in addition to OnaBai answer I had to use the sync function on the save method. I am using Type Script.
this.treeData = new kendo.data.HierarchicalDataSource({
data: kendo.observableHierarchy([]),//Thanks OnaBai
schema: {
model: {
id: "MenuItemId",
children: "MenuItemChildren",
hasChildren: (e) => {
//this removes arrow next to items that do not have children.
return e.MenuItemChildren && e.MenuItemChildren.length > 0;
}
}
}
});
public save() {
this.treeData.sync().done(() => {
console.log("sync data");
var myType = this.treeData.view();
this.$http.post("/api/TreeViewPicker", myType)
.then((response) => {
});
});
}

Populating dropdown list with JSON data using 2 views/documents

I'm having some trouble populating a dropdownlist with some JSON data, i suspect that the error occurs because of the way im appending the $.post within the #stuff div, but i've tried this a couple of ways and just wont get the hang of it.
The select id="" tag & the div lies within another view (it's not part of this particular document) , is that a problem for populating the dropdown-list this way?
Ive tried to alert out the "listItems" and i've got the option values etc... dont get it why it wont populate.
Any help would be appreciated.
Json-response from the $.post =
{"childrendata":[{"id":"42","parent":"1","fName":"hej","lName":"nisse","birthdate":"2011-10-21"}]}
The jQuery/js:
$("#stuff").append(function(){
$.post("show_relations", {},
function(data)
{
$("#stuff").empty();
json = eval('('+data+')');
if(data == '{"childrendata":[]}')
{
$("#stuff").append("No relations registered.");
}
else
{
var listItems= "";
for (var i = 0; i < json.childrendata.length; i++)
{
listItems+= "<option value='" + json.childrendata[i].fName + "'>" + json.childrendata[i].lName + "</option>";
}
$("#child_list").html(listItems);
}
});
});
});
Edit: Based on your comment, I'll assume your problem is purely single-page.
The problem with that code would appear to be the fact that you're trying to use .append() with a function (which is valid jQuery), but that the function doesn't return anything that jQuery can append to the 'stuff' node; $.post makes an Ajax call, which returns immediately.
Instead, try something like the following (modifying the URL to the Ajax call as required):
$.post("url/to/post/to", {},
function(data) {
$("#stuff").empty(); //Clear your stuff div
var children = data.childrendata; //jQuery automatically unserializes json
if(children.length == 0) {
$("#stuff").append("No relations registered.");
}
else {
$('#stuff').append('<select id="child_list"></select>');
$.each(children,
function(index, value) {
//Append each option to the selectbox
$("#child_list").append("<option value='" + value.fName + "'>" + value.lName + "</option>");
}
);
}
},
'json'
);
$.each() is the generic jQuery iterator, which helps de-clutter the code.
What this does is make an Ajax post to the provided URL, which responds with the serialized json object. The callback takes that response (which jQuery has already unserialized by itself), adds a new select to the '#stuff' div, and then adds the dynamically-created options to the new select.
Endnote: My apologies for not posting the link to the $.each documentation, StackOverflow only allows me to post 2 hyperlinks in a single post currently.

How to send dynamically generated variables via ajax, using post method

I've an html page wich contains a table, some rows and inside any row i checkbox.
When i select a checkbox i will to delete the message BUT only when i click a red-button-of-death.
Example
table
tr(unique_id)
td [checkbox]
td Content
td Other content
[... and so on]
/table
[red-button-of-death]
Now, the delete of multi rows must be without the reload of the page so i set up an ajax function that work like this:
setup ajax object.
set the open method (post/get, url, true)...
wait for the response of the "url" page.... take a coffe, have a break.
got response, using jquery delete the row using the unique id of the rows.
jquery: popup a feedback for the action just done
jquery: update some counter around the page
So, i begin tryin to delete a single record and everything go fine, i has created a link on every rows that call the function to delete "single record" passing the id of the item.
But now i've to develop the multi-delete-of-doom.
the first thing that i've think was "i can envelop the table in a 'form' and send everything with the 'post' method".
That seems to be brilliant and easy....
but doesn't work :-|
Googling around i've found some example that seems to suggest to set a variable that contains the item to send... so, trying to follow this way i need a method to get the name/id/value (it's not important, i can populate an attribute with the correct id) of the selected checkbox.
Here the function that make the ajax call and all the rest
function deleteSelected() {
var params = null;
var xmlhttp;
if (window.XMLHttpRequest) {// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp = new XMLHttpRequest();
}
else {// code for IE6, IE5
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.open("post", "./cv_delete_pm.php?mode=multi", true); //cancella i messaggi e ritorna l'id delle righe da cancellare
//Send the proper header information along with the request
http.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
http.setRequestHeader("Content-length", params.length);
http.setRequestHeader("Connection", "close");
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4) {
if (xmlhttp.status != 404) {
var local = eval( "(" + xmlhttp.responseText + ")" );
/*
//cancella gli elementi specificati dalla response
var Node = document.getElementById(local.id);
Node.parentNode.removeChild(Node);
loadMessagesCount('{CUR_FOLDER_NAME}'); //aggiorna sidebar e totale messaggi nel body
initTabelleTestate(); //ricrea lo sfondo delle righe
$("#msgsDeleted").attr("style", "left: 600px; top: 425px; display: block;");
$("#msgsDeleted").fadeIn(500);
$("#msgsDeleted").fadeOut(2000);
$("#msgsDeleted").hide(0);
*/
}
}
};
xmlhttp.send(params);
}
Actually the variable 'param' is set to null just because i'm doing some experimentation.
So, the questions
are:
- Is it possible to make an ajax request sending the content of the form? How?
- Is it possible to get the name/value/id (one of these) of all the selected checkbox of an html page? How?
Answer to one of these two question with the solution is enough to win my personal worship :)
Edit: I think you are using JQuery so look here: http://api.jquery.com/category/ajax/
You should be using a javascript frame work such as dojo or jquery to handle Ajax. Writing you own ajax functions from scratch is not recommended.
Some frameworks:
http://www.dojotoolkit.org/
http://www.jquery.com/ (http://api.jquery.com/category/ajax/)
http://mootools.net/
A jquery example (are you already using this framework?):
$.post("test.php", $("#testform").serialize());
A Dojo Example:
Submitting a form using POST and Ajax:
function postForm() {
var kw = {
url: 'mypage.php',
load: function(type, data, evt) {
dojo.byId("someElement").innerHTML=data;
},
formNode: dojo.byId("myForm"),
method: "POST",
error: function(type, data, evt){
//handle error
},
mimetype: "text/html"
};
dojo.io.bind(kw);
}
Update. Solved.
I've used the builtin function of jquery to manage the form sumbit using the $jQuery.post() function and the $(#idform).serialize() function. It's really late now but tomorrow i'll try to remember to paste here the correct code :)
Thanks for the answer anyway :)
Update (code below):
//Send by Post
function deleteSelected() {
$.post("./delete.php?mode=multi",
$("#pmfolder_form").serialize(),
function(data){
var local = eval( "(" + data + ")" );
//this delete the html via dom to update the visual information
for (var i = 0; i < local.length-1; ++i) {
var Node = document.getElementById(local[i]);
Node.parentNode.removeChild(Node);
}
});
}
The structure of the selectbox was something like:
<input type="checkbox" name="check_<? print $progressive_id; ?>" value="<? print $real_id; ?>"/>
That's all. :)