Delete operation using KnockoutJS and Entity Framework 6 - entity-framework

i'm having a problem with the delete operation using KOjs and EF6.when i click the remove button the confirmation dialog appears but the selected row is not deleted.
This is my controler:
public JsonResult FetchActivities()
{
return Json(_account.FindAllActivities(), JsonRequestBehavior.AllowGet);
}
[System.Web.Mvc.HttpDelete]
public void DeleteActivity(int id)
{
try
{
if (id != 0)
{
_account.Delete(id);
}
}
catch
{
throw new HttpResponseException(HttpStatusCode.BadRequest);
}
}
and this is the view:
<table class="table table-striped table-bordered table-condensed">
<tr>
<th>URL</th>
<th>Thumbnail</th>
<th>Title</th>
</tr>
<tbody data-bind="foreach: Activities">
<tr>
<td data-bind="text: urlactivite"></td>
<td data-bind="text: thumbnail"></td>
<td data-bind="text: title"></td>
<td><button class="btn btn-mini btn-danger" data-bind="click: $parent.removeActivity">remove</button></td>
</tr>
</tbody>
and here is the view model:
var ProfilesViewModel = function () {
var self = this;
var url = "/WhiteList/FetchActivities";
var refresh = function () {
$.getJSON(url, {}, function (data) {
self.Activities(data);
});
};
// Public data properties
self.Activities = ko.observableArray([]);
self.removeActivity = function (profile) {
if (confirm("Are you sure you want to delete this profile?")) {
var id = profile.id;
waitingDialog({});
$.ajax({
type: 'DELETE', url: '/WhiteList/DeleteActivity/' + id,
success: function () { self.Activities.remove(profile); },
error: function (err) {
var error = JSON.parse(err.responseText);
$("<div></div>").html(error.Message).dialog({ modal: true, title: "Error", buttons: { "Ok": function () { $(this).dialog("close"); } } }).show();
},
complete: function () { closeWaitingDialog(); }
});
}
};
refresh();
};
ko.applyBindings(new ProfilesViewModel());
I see no errors in my code.Can any one help me

Your code has several mistakes:
the only observable property is the Activities observable array: when you load the data with refresh() you are creating an observable array of regular, non-observable, objects. That means that ypu are trying to make bindings between the regular, non-observable properties of your array and your activities.
you're not passing any parameter to your removeActivity, and you are expecting to get a profile (what is that) and get it's id to delete it.
You'd need to make modifications to your model:
Create an Activity constructor with the same properties of the activity, but declared as observable properties
One of these 2 options
Include the removeActivity in the Activity constructor, to get the id of the activity to remove using this (or self)
Include removeActivity in the root for your model, and recive the id as parameter, and pass the id of the activity in the click binding
Modify refresh so that you map each element of the received activities to a new Activity object created with your constructor
If you choose option 2.2 you can make it automatically using knockout mapping.
Please, look at your code and try to see why you expected to receive a profile in removeACtivity function. I suppose you'll understand it made no sense.

Related

axios call to Laravel function retured Promise object error

I have to get data from the Laravel model function.
public function getTank($id)
{
$tank = Tank::find($id);
return $tank->tankno;
}
For this, the following function is being called.
async function getTank(tank){
let url = '/gettank/'+tank;
let abc= await axios.get(url)
.then(function(response){
return (response.data);
})
.catch(function(error){
console.log(error);
});
return(abc)
}
and passing tankno from vue code
<tr v-for="(item, index) in fdetail" :key="item.id">
<td>
{{getTank(item.id)}}
</td>
</tr>
I want to display returned data but the result is Promise Object.

How can I send a single string value through View Form in my webAPI?

How can I send a single string value through view from in the WebAPI made in ASP.NET core.
Here is my API:
[HttpPost]
[Route("studentlogin/{value}")]
public IActionResult StudentLogin(string value)
{
string name = String.Concat(value.Where(s => !Char.IsWhiteSpace(s)));
name = name.ToLower();
var newStudent = new Student();
newStudent.FullName = name;
db.Entry(newStudent).State = EntityState.Added;
db.SaveChanges();
var selectStudent = db.Students.Where(ss => ss.FullName == name).FirstOrDefault();
var id = selectStudent.Id;
string idToString = id.ToString();
string answer = sha384converter(idToString);
selectStudent.HashId = answer;
db.Entry(selectStudent).State = EntityState.Modified;
db.SaveChanges();
return Ok();
}
I want to send paramenter value in it through View Forms, How can I send data in it?
Thanks in advance.
[Route("studentlogin/{value}")]
If you are using the above route, the request URL should like this: https://localhost:44310/api/apicontrollername/studentlogin/XXX, the parameter will be transferred from the URL and route.
to send paramenter value in it through View Forms, How can I send data
in it?
To send parameter value from posted form fields, you could modify the code as below:
In the API controller, remote the route parameter and add the FromForm attribute.
[HttpPost]
[Route("studentlogin")]
public IActionResult StudentLogin([FromForm]string value)
{
string name = "Default value";
if (!string.IsNullOrEmpty(value))
{
name = String.Concat(value.Where(s => !Char.IsWhiteSpace(s)));
}
... // add your code
return Ok(name);
}
Then, create a model which contain the value property, like this:
public class StudentLoginViewModel
{
public string value { get; set; }
}
In the View page, display the above model in the form:
#model WebApplication6.Models.StudentLoginViewModel;
<form id="myform">
<div class="form-group">
<label asp-for="value" class="control-label"></label>
<input asp-for="value" class="form-control" />
<span asp-validation-for="value" class="text-danger"></span>
</div>
<div class="form-group">
<input type="button" id="btnsubmit" value="Submit" class="btn btn-primary" />
</div>
</form>
and add the following script at the end of the above view page:
#section Scripts{
<script>
$(function () {
$("#btnsubmit").click(function () {
//use the serialize() method to encode a set of form elements as a string for submission
var data = $("#myform").serialize();
//you can also create JavaScript object and send the data.
//var data = { value: $("#value").val() };
$.ajax({
url: '/api/todo/studentlogin', // change the url to yours.
type: "post",
contentType: 'application/x-www-form-urlencoded',
data: data,
success: function (result) {
console.log(result);
}
});
});
})
</script>
}
The result as below:

Knockout event binding with condition

I want to bind some events to an element , using the knockout "event" binding
But I want all of the listed events to be bound only with a specific case.
The viewmodel:
function vm(){
var self = this;
self.isEditMode = ko.observable(false);//can be changed to true
self.events = ko.observable({
down: function () {
console.log("down")
},
up: function () {
console.log("up")
},
hover: function () {
console.log("hover")
}
});
}
and the Html:
<div style="border:1px solid red;width:50px;height:50px"
data-bind="event:{mousedown:events().down,mouseup:events().up,mouseover:events().hover}:null"></div>
<button data-bind="click:function(){isEditMode(!isEditMode())}">change </button>
I tried:
<div data-bind="event:isEditMode()?{mousedown:events().down,mouseup:events().up,mouseover:events().hover}:null"></div>
But it did not work for me.
I think the best way to do it is by using custom bindingHandlers, but I dont know how.
Thank you very much for your help!
You can simplify the the binding by moving some logic into the view model
<div style="border:1px solid red;width:50px;height:50px"
data-bind="event: {
mousedown: down,
mouseup:up,
mouseover:hover }" > </div>
and view model like this
function vm() {
var self = this;
this.isEditMode = ko.observable(true);
down = function() {
if(this.isEditMode())
{
console.log("down")
}
};
up = function() {
if(this.isEditMode())
{
console.log("up")
}
};
hover = function() {
if(this.isEditMode())
{
console.log("hover")
}
};
}
var viewModel = new vm();
ko.applyBindings(viewModel);
Another option is to place the condition in the markup itself as two separate blocks using an "if" binding to determine which ones gets shown and bound.
function vm() {
var self = this;
self.isEditMode = ko.observable(false); //can be changed to true
self.events = ko.observable({
down: function() {
console.log("down");
},
up: function() {
console.log("up");
},
hover: function() {
console.log("hover");
}
});
}
ko.applyBindings(new vm());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<!--ko if: isEditMode()-->
<div style="border:1px solid red;width:50px;height:50px" data-bind="event:{
mousedown:events().down,
mouseup:events().up,
mouseover:events().hover
}">
Edit Mode
</div>
<!--/ko-->
<!--ko if: !isEditMode()-->
<div style="border:1px solid red;width:50px;height:50px">
Read Only
</div>
<!--/ko-->
<button data-bind="click:function(){isEditMode(!isEditMode())}">change </button>

kendo mvvm not updating after ajax call

I have a page (relevant code below) which carries out the following :
User enters a value into an auto-complete text box
2, Upon selecting an auto complete option, an ajax call is made in order to fill 2 dropdownlists
User is required to select a value from each dropdownlist
Once a value has been selected on both, they click on the add button and my bound table is updated
User can remove rows added to the table
The rows added in step 4 are contained in an array in the observable object.
The first time the page loads points 1 to 5 work as expected.....
However, if the user enters a new search into the auto-complete box and fires the select event, the second time the ajax call is made, the relationship between my viewmodel and UI objects are broken.
The code which is executing is identical so please could someone shed some light on why the second time around this breaks.
<input type="text" id="txtBox" style="width:300px;" />
<div id="fixturesBindable" style="padding:0 !Important;">
<table>
<thead>
<tr>
<th>Col1</th>
<th>Col2</th>
</tr>
</thead>
<tbody data-template="row-template" data-bind="source: Fixtures"></tbody>
</table>
<select id="a_teamsdropdown" data-role="dropdownlist" data-text-field="TeamFullName" data-value-field="Id" data-bind="source: Teams" style="width:200px;"></select>
<select id="a_oppteamsdropdown" data-role="dropdownlist" data-text-field="TeamFullName" data-value-field="Id" data-bind="source:
OpponentTeams" style="width:200px;"></select>
<button type="button" data-bind="click: addFixture">Add Fixture</button>
<script id="row-template" type="text/x-kendo-template">
<tr>
<td><input type="hidden" id="team" data-bind="attr: { name: TeamModelName, value: TeamId }" /></td>
<td><input type="hidden" id="oppteam" data-bind="attr: { name: OppModelName, value: OppTeamId }" /></td>
</tr>
</script>
</div>
<script>
$(document).ready(function () {
var viewModel = kendo.observable({
Teams: <%= Model.Teams %>,
OpponentTeams: [],
Fixtures: [],
addFixture: function (e) {
var Fixtures = this.get("Fixtures");
var teamId = $("#a_teamsdropdown").val();
var teamName = $("#a_teamsdropdown>option:selected").text();
var oppteamId = $("#a_oppteamsdropdown").val();
var oppteamName = $("#a_oppteamsdropdown>option:selected").text();
this.get("Fixtures").push({
TeamFullName: teamName,
TeamId: teamId,
OppTeamFullName: oppteamName,
OppTeamId: oppteamId,
OrderIndex: this.get("Fixtures").length,
TeamModelName: 'Fixtures[' + this.get("Fixtures").length + '].TeamId',
OppModelName: 'Fixtures[' + this.get("Fixtures").length + '].OpponentTeamId'
});
},
resetFixture: function(){
var Fixtures = this.get("Fixtures");
$.each(Fixtures, function (key, fixture) {
Fixtures.splice(0, 1);
});
}
});
opponents = $("#txtBox").kendoAutoComplete({
minLength: 3,
dataTextField: "Name",
filter: "contains",
dataSource: new kendo.data.DataSource({
transport: {
read: {
url: "/url/Ajax",
type: "POST",
data: function () { return { searchText: $("#txtBox").val()}
},
complete: function (data) {
opponents.list.width(400);
}
}
},
pageSize: 10,
serverPaging: true,
serverSorting: true,
schema: {
total: "count",
data: "data",
model: {
id: "Id",
fields: {
Id: { editable: false }
}
}
}
}),
change: function () {
this.dataSource.read();
},
select: function (e) {
$.each(opponents.dataSource.data(), function (index, value) {
if (e.item.text() == value.Name) {
selectedOpponent = value;
$('#Fixture_OpponentTeam_Id').val(selectedOpponent.Id);
$('#OpponentName').val(selectedOpponent.Name);
$.ajax({
url: 'GetOpponentTeams',
data: { schoolId: selectedOpponent.Id, seasonId: seasonId, sportId: sportsId },
type: 'GET',
success: function (data) {
viewModel.OpponentTeams = data;
kendo.bind($("#fixturesBindable"), viewModel);
},
error: function (xhr, ajaxOptions, thrownError) {
//alert('Error during process: \n' + xhr.responseText);
alert(thrownError);
}
});
return;
}
});
}
}).data("kendoAutoComplete");
</script>
Not sure if this will fix your issue or not, but in general I would advise against re-binding everything in your ajax success callback. If you just .set("OpponentTeams") instead of assigning the value directly, does that help?
success: function (data) {
viewModel.set("OpponentTeams", data);
},
The call to .set() should trigger a refresh of the #a_oppteamsdropdown element.

Editing IEnumerable Model Property in MVC View

I have a situation where I need to edit an enumerable property in a view model:
public class ViewModel
{
public MyObj Obj { get; set; }
public IEnumerable<MyObj> MyObjs = new List<MyObj>();
}
I have followed this post; controller action:
public ActionResult Index()
{
var viewModel = new ViewModel();
viewModel.Obj = new Obj() { Name = "0", Value = true };
var o1 = new MyObj() { Name = "1", Value = false };
var o2 = new MyObj() { Name = "2", Value = false };
viewModel.Objs = new List<Obj>() { o1, o2 };
return View(viewModel);
}
[HttpPost]
public ActionResult Index(ViewModel viewModel)
{
return View(viewModel);
}
The Index view as follows:
<% using (Html.BeginForm()) { %>
<table>
<tr>
<th>Name</th>
<th>Value</th>
</tr>
<%= Html.EditorFor(x => x.Objs) %>
</table>
<br />
<input type="submit" value="Submit" />
<% } %>
And the editor template in "~/Views/Home/EditorTemplates/Obj.ascx":
<tr>
<td><%: Html.TextBoxFor(x => x.Name) %></td>
<td><%: Html.CheckBoxFor(x => x.Value) %></td>
</tr>
The issue is: browse to Index, the data shows up. The POST, and the enumerable data disappears. Stepping through, the singular "Obj" in the view model remains, so it is just the enumerable data that is disappearing.
I have been staring at this for some time now, if any one could help out it would be brilliant.
Cheers,
Tim.
Take a look at this post by Phil Haack, MVC2 doesn't natively support binding a list back to the viewmodel unless you do a little manipulation.
Update: I've looked into this a little more and think you should try adding TryUpdateModel(viewModel.MyObjs, "MyObjs"); to your Controller. This informs the modelbinder that it should use the "MyObjs" binding prefix to attach the data from the form to the collection in your ViewModel.