List<KeyValuePair<string, string>> MVC/Angular form save issues - javascript

I have a form to enter a list of key value pairs. When I enter data into the input fields or add a new keyvalue pair everything displays fine on the client side and I can see the Model updating. The problem comes when I go to save the newly created list. The list get passed to the angular save function just fine with all the data in place. The problem occurs between the angular save function and my MVC controller save function. The right number of key value pairs get sent to the MVC controller functions parameters, but all of the information has now been set to null.
So on the client side my model looks like this.
[{"Key":"this","Value":"has"},{"Key":"data","Value":"in"},{"Key":"it","Value":"see"}]
which is what I want, but when it reaches my MVC controller as a parameter it looks like this.
[{"Key":null,"Value":null},{"Key":null,"Value":null},{"Key":null,"Value":null}]
Which is not what I want. Any help with this will be greatly appreciated. Thank You.
Here is my MVC controller function.
public JsonResult SaveSettings(List<KeyValuePair<string, string>> replacementPaths)
{
JobSchedulerConfig config;
config = Biz.GetConfig();
config.ReplacementPaths = replacementPaths;
return null;
}
My Angular controller and save logic.
$scope.save = function () {
SettingsService.saveSetting($scope.settings)
.success(function (data) {
//alert(data);
})
.error(function (error) {
$scope.status = 'Unable to load data: ' + error.message;
});
};
SettingsApp.factory('SettingsService', ['$http', function ($http) {
var SettingsService = {};
SettingsService.getSettings = function () {
return $http.get('#Url.Action("GetReplacementPaths", "Setting")');
};
SettingsService.saveSetting = function (data) {
//alert(data);
alert(data.toSource());
//data = angular.stringify(data);
return $http.post('#Url.Action("SaveSettings", "Setting")', data );
};
return SettingsService;
}]);
And my view markup.
<div ng-app="SettingsApp">
<div ng-controller="SettingsController">
<div ng-repeat="kvp in settings">
<input ng-model="kvp.Key" />
<input ng-model="kvp.Value" />
<button ng-click="delete(settings, kvp)">Delete</button>
</div>
<button class="btn btn-default" ng-click="addSetting()">Add Setting</button>
<button type="submit" name="config" ng-click="save()" class="btn btn-default btn-primary">Save Config</button>
{{settings}}
</div>
</div>
Again thanks for any help.

Related

Update knockout viewmodel after ajax call

I am having an issue saving changes back to my observable viewmodel using KnockoutJS. To keep this simple I will just show the basics....My viewmodel has a class called EmployeeSkill, which has two properties and the EmployeeSkillsViewModel is an array that contains zero to many of these skills as shown below in my Index.cshtml page. I have a variable: ctrl which holds a reference to the input control next to the button I click to open a modal dialog which allows the user to enter an existing OR new value in its input control. When the save button is clicked the database is checked or updated and an integer value is returned. I would like to save this returned value to my model.
The viewmodel is populated with JSON that looks like this:
[{"EmployeeSkillId": 1, "SkillsId": 999}, {"EmployeeSkillId": 2, "SkillsId": 777}, {"EmployeeSkillId": 3, "SkillsId": 888}]
<script type="text/javascript">
var ctrl;
$(document).on("click", ".open-editSkillName", function () {
ctrl = $(this).closest('.input-group').find('input');
$(".modal-body #edit_skill_name").val($(this).closest('.input-group').find('input').val());
});
$(function () {
function EmployeeSkillsViewModel() {
var self = this;
self.EmployeeSkillId = ko.observable("");
self.SkillsId = ko.observable("");
var EmployeeSkill = {
EmployeeSkillId: self.EmployeeSkillId,
SkillsId: self.SkillsId,
};
self.EmployeeSkill = ko.observable();
self.EmployeeSkillsArray = ko.observableArray();
self.updateSkillName = function (ctrl) {
var skillName = $(".modal-body #edit_skill_name").val();
$(ctrl).val(skillName);
// Check to see if this skill exists...
$.ajax({
url: '#Url.Action("UpsertSkill", "EmployeeSkills")',
cache: false,
type: 'POST',
contentType: 'application/json; charset=utf-8',
data: ko.toJSON({ 'skillName': skillName }),
success: function (data) {
// alert(data.SkillsId) --> alerts expected int value
self.SkillsId(data.SkillsId);
ko.applyBindings(self.EmployeeSkillsArray);
}
}).fail(function (xhr, textStatus, err) {
alert(err);
});
}
var viewModel = new EmployeeSkillsViewModel();
ko.applyBindings(viewModel);
});
</script>
I have a modal popup that allows the user to enter a value into the input and when they click the btnSaveSkillName the function updateSkillName (above) is called
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<button type="button" class="close-editSkillName btn btn-primary" data-dismiss="modal" id="btnSaveSkillName" data-bind="click: $root.updateSkillName(ctrl)">Update Skill Name</button>
</div>
I pass this value in the skillName property to my controller and return in my response an integer value with the id of the skill name entered. I would like to update the row of underlying view model with this new integer value but I am not finding an easy way to do so.

How Insert AngularJS JSON Data Into SQL

So I am currently working on an application that uses WebAPI and AngularJS to search for some data from a SQL table and display it on a webpage for the user to select multiple individual rows of data. I am inserting the selected rows into a separate JSON array (availableclients) that I would like to insert into a separate SQL table. What is the best method for me to take my array of JSON data and insert it into a different SQL table. I will attach the code I am currently using to get the data.
Controller.js
var app = angular.module('myApp', []);
app.controller("myController", function ($scope, $http) {
function getCert(myid) {
$http.get('api/Cert/Get/', { params: { id : myid } })
.success(function (data) {
$scope.selectedclients = data;
})
}
$scope.searchClick = function() {
getCert($scope.myid);
}
$scope.moveItem = function (item, from, to) {
var idx = from.indexOf(item);
if (idx != -1) {
from.splice(idx, 1);
to.push(item);
}
};
$scope.availableclients = [];
});
HTML
<html data-ng-app="myApp">
<body data-ng-controller ="myController">
My_ID: <input type="text" ng-model="my_id" />
<input type="submit" value="Search" ng-click="searchClick()" />
<select size="10" multiple ng-model="selected" ng-options="i.unit_id for i in selectedclients" style="width: 400px"></select>
<div class="btn-group">
<button title="Remove From List" class="btn btn-default" ng-click="moveItem(available[0], availableclients,selectedclients)"><i class="glyphicon glyphicon-chevron-left"></i></button>
<button title="Add To List" class="btn btn-default" ng-click="moveItem(selected[0], selectedclients,availableclients)"><i class="glyphicon glyphicon-chevron-right"></i></button>
</div>
<select size="10" multiple ng-model="available" ng-options="i.unit_id for i in availableclients" style="width: 400px"></select>
</body>
</html>
The code I have is working fine I am just at a loss for how to take my availableclients JSON array and insert it into my SQL table. This is probably really easy to do but all my searches are coming up blank on what I am looking for exactly. Any help is appreciated. Thanks!
EDIT 1: On recommendation of a comment I am adding the Controller I used for the Web API get. Again thanks for any advice!
public class CertController : ApiController
{
CertEntities objapi = new CertEntities();
[HttpGet]
public IEnumerable<AngularCoCSelect_Result> Get(int id)
{
return objapi.AngularCoCSelect(id).AsEnumerable();
}
}
It is quite wide question... also you are showing the client code and nothing from the backend which eventually will store the data (suspecting as you put asp.net tag also)
So based on that You can use Entity Framework to store your data into a database. You may find a lot of articles on the internet about implementing this approach.
This solution as guide line
need back-end api that accept array of object (json) for your clients ASP.NET or PHP then
You need to add function in Angular within your controller for submit client data to the server using $http.put or $http.post
$scope.submitClientData = function(){
$http.post('webapi/clients' , { clients:$scope.availableclients })
}
You may call function from submit button
<button ng-click='submitClientData()'>Save</button>

AngularJS - how to not display HTML element until the variable it is binded to is loaded in the JS?

This is my HTML:
<button type="button" class="btn btn-primary" ng-hide="ctrl.userProfile.following">Follow</button>
<button type="button" class="btn btn-primary" ng-show="ctrl.userProfile.following">Unfollow</button>
So basically, I want to hide the "Follow" button and show the "Unfollow" button if ctrl.userProfile.following is true, and vise-versa.
This is my back-end:
self.userProfile = {};
function fetchUserProfile() {
$http.get('/users/' + username)
.then(function(response) {
self.userProfile = response.data;
}, function(response) {
self.cerrorMessages = BaseService.accessErrors(response.data);
});
};
fetchUserProfile();
So I get the userProfile and then update self.userProfile with the watching variable (this occurs when I do self.userProfile = response.data. With that said, is there a way for me to tell HTML to not display the buttons until self.userProfile is filled with watching variable?
Create a userProfile.ready flag and use that to control the showing of the Follow and Unfollow buttons.
HTML
<div ng-show="ctrl.userProfile.ready">
<button type="button" ng-hide="ctrl.userProfile.following">Follow</button>
<button type="button" ng-show="ctrl.userProfile.following">Unfollow</button>
</div>
JS
self.userProfile = {};
self.userProfile.ready = false;
function fetchUserProfile() {
self.userProfile.ready = false;
$http.get('/users/' + username)
.then(function(response) {
self.userProfile = response.data;
self.userProfile.ready = true;
}, function(error) {
self.cerrorMessages = BaseService.accessErrors(error.data);
});
};
fetchUserProfile();
There are a few ways of doing this. Here is one:
If you start with an empty object, and are waiting for the promise to resolve, you can set a scope variable that checks the length of the object.
e.g.
self.userProfileLength = Object.keys(self.userProfile).length;
And in the view, do: ng-if="ctrl.userProfileLength"
(Note: Or use ng-show if you want to keep the element in the DOM)
Object.keys returns the keys from the object in an array. Anything over a length of 0 is a truthy value so it will pass the ng-if condition.

Updating multi-model form from Angular to Sinatra

I'm currently having an issue with updating a form in Angular and pushing the update through to Sinatra.
It is supposed to:
When clicked, the form to edit the current item is shown (current data for each field is displayed from the item scope).
When submitted, it is attempting to update to a different scope (updateinfo). I am not sure but do I need a way of using multiscope or one scope to allow it to update?
At present the script sends the correct downloadID parameter, but the JSON from the scope submitted is as I believe, incorrect.
Also, I'm not sure whether the Sinatra app.rb syntax is correct, for someone new to these frameworks, it has been hard to find useful documentation online.
If anybody could help it would be very much appreciated.
downloads.html
<div ng-show="showEdit">
<form ng-submit="updateinfo(item.downloadID); showDetails = ! showDetails;">
<div class="input-group"><label name="title">Title</label><input type="text"
ng-model="item.title"
value="{{item.title}}"/></div>
<div class="input-group"><label name="caption">Download caption</label><input type="text"
ng-model="item.caption"
value="{{item.caption}}"/>
</div>
<div class="input-group"><label name="dlLink">Download link</label><input type="url"
ng-model="item.dlLink"
value="{{item.dlLink}}"/>
</div>
<div class="input-group"><label name="imgSrc">Image source</label><input type="url"
ng-model="item.imgSrc"
value="{{item.imgSrc}}"/>
</div>
<!-- download live input types need to be parsed as integers to avoid 500 internal server error -->
<div class="input-group"><label name="imgSrc">
<label name="dlLive">Download live</label><input type="radio" ng-model="download.dl_live"
value="1"/>
<label name="dlLive">Not live</label><input type="radio" ng-model="download.dl_live"
value="0"/></div>
<div class="input-group"><label name="imgSrc"><input type="submit"/></div>
</form>
controllers.js
$scope.loadData = function () {
$http.get('/view1/downloadData').success(function (data) {
$scope.items = data;
});
};
$scope.loadData();
$scope.updateinfo = function(downloadID) {
id = downloadID
var result = $scope.items.filter(function( items ) {
return items.downloadID == id;
});
console.log(result);
updatedata = $scope.items
$http({
method : 'PUT',
url : '/view1/downloadedit/:downloadID',
data : result
});
};
app.rb
#edit download
put '/view1/downloadedit' do
puts 'angular connection working'
ng_params = JSON.parse(request.body.read)
puts ng_params
#download = Download.update(ng_params)
end
The wrong scope was attempting to be used. Once the scope was corrected to items, the correct JSON was being routed:
$scope.updateinfo = function(downloadID) {
id = downloadID
var result = $scope.items.filter(function( items ) {
return items.downloadID == id;
});
console.log(result);
updatedata = $scope.items
$http({
method : 'PUT',
url : '/view1/downloadedit/:downloadID',
data : result
});

Sending POST with hidden <input> value does't work in AngularJs

In my web app, There are many form on a page. I want to submit it with AngularJS for specific form.
In each of form, it need unique ID with Hidden Value to submit. But value="UNIQUE_ID" seen doesn't work in hidden input box in AngularJS.
My HTML
<div ng-app>
<div ng-controller="SearchCtrl">
<form class="well form-search">
<input type="text" ng-model="keywords" name="qaq_id" value="UNIQUE_ID">
<pre ng-model="result">
{{result}}
</pre>
<form>
</div>
</div>
This is js script
function SearchCtrl($scope, $http) {
$scope.url = 'qa/vote_up'; // The url of our search
// The function that will be executed on button click (ng-click="search()")
$scope.search = function() {
// Create the http post request
// the data holds the keywords
// The request is a JSON request.
$http.post($scope.url, { "data" : $scope.keywords}).
success(function(data, status) {
$scope.status = status;
$scope.data = data;
$scope.result = data; // Show result from server in our <pre></pre> element
})
.
error(function(data, status) {
$scope.data = data || "Request failed";
$scope.status = status;
});
};
}
It may be that the only reason your code is not working is that $scope.keywords is a simple variable (with a text value) instead of an Object, which is required - see http://docs.angularjs.org/api/ng.$http#Usage
As angularJS works with variables within its own scope - its models, a form becomes just a way to interact with those models, wich can be sent via whatever method you want.
You can have a hidden field, yes, but in angularJS it isn't even necessary. You only need that information to be defined in the controller itself - randomly generated for each instance, or received from some other source.. Or you can define it yourself, upon the loading of the controller, for instance.
So (and only for sake of clarity) if you define a formData variable within your formCtrl:
Your HTML:
<div ng-app>
<div ng-controller="SearchCtrl">
<form class="well form-search">
<input type="text" ng-model="formData.title">
<input type="textarea" ng-model="formData.body">
<button ng-click="sendData()">Send!</button>
</form>
<pre ng-model="result">
{{result}}
</pre>
</div>
</div>
And your controller:
function SearchCtrl($scope, $http) {
$scope.url = 'qa/vote_up'; // The url of our search
// there is a formData object for each instance of
// SearchCtrl, with an id defined randomly
// Code from http://stackoverflow.com/a/1349426/1794563
function makeid()
{
var text = "";
var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
for( var i=0; i < 5; i++ )
text += possible.charAt(Math.floor(Math.random() * possible.length));
return text;
}
$scope.formData = {
title: "",
text: ""
};
$scope.formData.id = makeid();
// The function that will be executed on button click (ng-click="sendData()")
$scope.sendData = function() {
// Create the http post request
// the data holds the keywords
// The request is a JSON request.
$http.post($scope.url, { "data" : $scope.formData}).
success(function(data, status) {
$scope.status = status;
$scope.data = data;
$scope.result = data; // Show result from server in our <pre></pre> element
})
.
error(function(data, status) {
$scope.data = data || "Request failed";
$scope.status = status;
});
};
}
Also: If you wanted to set the unique id on the html itself, you could add an input type="hidden" and set it's ng-model attribute to formData.id, and whichever value you set it to, the model would have it binded. using a hidden input won't work, as the value attribute doesn't update the angularJS Model assigned via ng-model. Use ng-init instead, to set up the value:
HTML with 2 forms:
<div ng-controller="SearchCtrl" ng-init="formData.id='FORM1'">
<form class="well form-search">
<input type="text" ng-model="formData.title">
<input type="textarea" ng-model="formData.body">
<button ng-click="sendData()">Send!</button>
</form>
</div>
<div ng-controller="SearchCtrl" ng-init="formData.id='FORM2'">
<form class="well form-search">
<input type="text" ng-model="formData.title">
<input type="textarea" ng-model="formData.body">
<button ng-click="sendData()">Send!</button>
</form>
</div>
You can add a hidden field, but it accomplishes nothing - the ng-init attribute does everything you need.

Categories

Resources