Prevent submitting of a form in asp.net mvc - asp.net-mvc

I'm using MVC Http.BeginForm to create a search form.
Now I want to add create button, which opens Popup, but when I press it HttpPost event in controller fires up. How can I prevent HttpPost event to fire up when popup is pressed?
#using (Html.BeginForm())
{
<table border="0">
<tr>
<td style="padding: 5px;">A:</td>
<td style="padding: 5px;">#Html.TextBox("slicplate", "", new { style="width:120px; height:25px;" })</td>
<td style="padding: 5px;">B:</td>
<td style="padding: 5px;">#Html.TextBox("smodelis", "", new { style="width:120px; height:25px;" })</td>
<td style="padding: 5px;">C:</td>
<td style="padding: 5px;">#Html.TextBox("suzsakovas", "", new { style = "width:120px; height:25px;" })</td>
<td style="padding: 5px;">D:</td>
<td style="padding: 5px;">#Html.TextBox("svairuotojas", "", new { style = "width:120px; height:25px;" })</td>
<td style="padding: 5px;" rowspan="3" valign="top"><input type="submit" value="Search" style="height:59px;" /></td>
<td style="padding: 5px;" rowspan="3">
<button class="btn btn-primary" style="height:50px; width:100px;" ng-click="open('new_tp')">Popup button</button>
</td>
</tr>
</table>
}
Open function:
var ModalDemoCtrl = function ($scope, $modal, $log) {
$scope.items = ['item1', 'item2', 'item3'];
$scope.open = function (size, id) {
var modalInstance
if (size == "new_tp") {
modalInstance = $modal.open({
templateUrl: '/Transport/Create',
controller: ModalInstanceCtrl,
size: size,
resolve: {
items: function () {
return $scope.items;
}
}
});
}
modalInstance.result.then(function (selectedItem) {
$scope.selected = selectedItem;
}, function () {
$log.info('Modal dismissed at: ' + new Date());
});
};
};
And ModalDemoCtrl function:
var ModalInstanceCtrl = function ($scope, $modalInstance, items) {
$scope.items = items;
$scope.selected = {
item: $scope.items[0]
};
$scope.ok = function () {
$('.modal-dialog').close;
$modalInstance.close($scope.selected.item);
};
$scope.delete = function (id) {
$('.modal-dialog').close;
$modalInstance.close($scope.selected.item);
};
$scope.cancel = function () {
$modalInstance.dismiss('cancel');
};
};

Change code from
<button class="btn btn-primary" style="height:50px; width:100px;" ng-click="open('new_tp')">Popup button</button>
To:
<button class="btn btn-primary" type="button" style="height:50px; width:100px;" ng-click="open('new_tp')">Popup button</button>

Related

ASP.NET MVC code modal popup not sending parameter to controller

I am trying to present Organization Details in a partial view in a Bootstrap Modal. After a day of reading/watching tutorials I am stumped.
Organizations are loaded into a Table and there is a View option on each row. The table has an id="OrganizationGrid"
<table class="table table-striped table-bordered dt-responsive nowrap" width="100%" cellspacing="0" id="OrganizationGrid">
<thead>
<tr style="color:#126E75; background-color:lightcyan">
<th style=" width:5%">
#Html.ActionLink("ID", "Index", new { sortOrder = ViewBag.IDSortParm, currentFilter=ViewBag.CurrentFilter })
</th>
<th style=" width:25%">
#Html.ActionLink("Name", "Index", new { sortOrder = ViewBag.NameSortParm, currentFilter=ViewBag.CurrentFilter })
</th>
<th style=" width:25%">
Parent Org
</th>
<th style=" width:10%; text-align:center">
Website
</th>
<th style="width:25%">
Comment
</th>
<th scope="col" colspan="3" style=" width:10%; text-align:center">Action</th>
</tr>
</thead>
<tbody>
#foreach (var item in Model) {
<tr class=" table-light">
<td style="text-align:left">
#Html.DisplayFor(modelItem => item.Id)
</td>
<td style="text-align:left">
#Html.DisplayFor(modelItem => item.Name)
</td>
<td style="text-align:left">
#Html.DisplayFor(modelItem => item.ParentOrg.Name)
</td>
<td style="text-align: center">
<a href=#Html.DisplayFor(modelItem=> item.Website) target="_blank">
<i class="fa-solid fa-globe" target="_blank" rel="noopener noreferrer"></i>
</a>
</td>
<td style="text-align:left">
#Html.DisplayFor(modelItem => item.Comment)
</td>
<td style="text-align: center">
<a asp-action="Edit" asp-route-id="#item.Id">
<i class="fas fa-edit"></i>
</a>
</td>
<td>
<a class="details" href="javascript:;">View</a>
</td>
<td style="text-align: center">
<a asp-action="Delete" asp-route-id="#item.Id">
<i class="fas fa-trash" style="color:red"></i>
</a>
</td>
</tr>
}
</tbody>
</table>
My understanding is that it triggers the JavaScript function which is currently residing at the bottom of the same page:
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<script type="text/javascript">
$(function() {
$("#OrganizationGrid .details").click(function() {
var organizationId = $(this).closest("tr").find("td").eq(0).html();
$.ajax({
type: "POST",
url: "/Organizations/Details",
data: '{organizationId: "' + organizationId + '" }',
contentType: "application/json; charset=utf-8",
dataType: "html",
success: function(response) {
$("#partialModal").find(".modal-body").html(response);
$("#partialModal").modal('show');
},
failure: function(response) {
alert(response.responseText);
},
error: function(response) {
alert(response.responseText);
}
});
});
});
</script>
I inserted a break in the controller to see if ajax was passing the organizationId but it is not. This is the Controller Details Action method:
[HttpPost]
public ActionResult Details(int organizationId)
{
var organization = _context.Organizations
.Include(o => o.ParentOrg).Where(p=>p.Id == organizationId);
if (organization == null)
{
return NotFound();
}
return PartialView("_Details", organization);
}
If I hard code organizationId in the Controller the popup loads with the correct information BUT if I hard code organizationId in the JavaScript function it still passes a null value to the controller. Could someone please point me in the right direction.
The issue was with the JavaScript function and specifically the syntax of the data attribute in ajax. Corrected solution is as follows:
$(function () {
$("#OrganizationGrid .details").click(function () {
var organizationId = $(this).closest("tr").find("td").eq(0).html();
//alert(organizationId)
$.ajax({
type: "POST",
url: "/Organizations/Details",
data: { 'id': organizationId },
//contentType: "application/json; charset=utf-8",
//dataType: "html",
success: function (response) {
$("#viewEditOrgModal").find(".modal-body").html(response);
$("#viewEditOrgModal").modal('show');
},
failure: function (response) {
alert(response.responseText);
},
error: function (response) {
alert(response.responseText);
}
});
});
});

Web api result updating model but not view in angularjs

I am calling Web-Api from angular-service and that returning data to my angular-controller.
$scope.$watch showing correct data, but view is not changing related data.
My Angularjs-Service is,
BDayModule.service("serviceUser", function ($http) {
this.getData = function () {
return $http.get('/Users/listAll').then(function (success) {
console.log("success.data 1 = " + success.data);
return success.data;
},
function (error) {
alert("Insertion fail");
},
function (process) {
});
};
});
My angularjs-controller is,
BDayModule.controller("ControllerUsers", function ($scope, $interval, serviceUser, commonFunction) {
$scope.allBDayData = [];
$scope.getAllUsers = function () {
var myDataPromise = serviceUser.getData();
myDataPromise.then(function (result) {
console.log("success.data 2 = " + result);
$scope.allBDayData = result;
$scope.$watch('allBDayData',
function (newValue, oldValue) {
console.log('allBDayData Changed');
console.log(newValue);
console.log(oldValue);
});
});
}
});
My view,
<div ng-controller="ControllerUsers">
<input type="button" value="Show all" ng-click="getAllUsers()" />
<table class="table table-bordered table-responsive table-hover">
<caption>
<span class="col-lg-2 col-sm-3"><input type="text" class="form-control" ng-model="Search.$" placeholder="Full filter" /></span>
</caption>
<thead>
<tr>
<th>User Name : <input type="text" ng-model="Search.UserName" placeholder="Filter" /></th>
<th>Email Address</th>
<th>First Name</th>
<th>Birth Date</th>
<th>Age</th>
<th><span aria-hidden="true" class="glyphicon glyphicon-edit"></span></th>
</tr>
</thead>
<tbody>
<tr ng-repeat="data in allBDayData | filter: Search">
<td>{{data.UserName}}</td>
<td>{{data.EmailId}}</td>
<td>{{data.Name}}</td>
<td>{{data.BirthDate}}</td>
<td>{{data.Age}}</td>
<td><input type="button" value="edit" class="btn btn-sm btn-success" style="width: 90px;" /></td>
</tr>
</tbody>
</table>
</div>
Button on which I click is in master page,
<li><a ng-controller="ControllerUsers" href="#list" ng-click="getAllUsers()"> Show All </a>
this button rendering page correctly based on routing, and firing getAllUsers() too. but not changing my view result...

Can not save data 2nd time knockout mvc

I am new in knockout and asp.net mvc both.
I am trying to Insert update delete data in database with knockout. My knockout model is
function City(data) {
this.CityId = ko.observable(data.CityId);
this.CityName = ko.observable(data.CityName);
}
function CityViewModel() {
var self = this;
self.Citys = ko.observableArray([]);
self.CityId = ko.observable();
self.CityName = ko.observable();
self.selectedCity = ko.observable();
// self.City = ko.observable();
selectCity = function (item) {
self.selectedCity(item);
}
//load
loadCitys = function () {
$.getJSON("/Admin/GetCitys", {}, function (result) {
var mappedCitys = ko.utils.arrayMap(result.Data, function (item) {
return new City(item);
});
self.Citys([]);
self.Citys.push.apply(self.Citys, mappedCitys);
});
}
//edit
EditCity = function (item) {
//what need to do here
// is it possible to fill the hidden fild and the text box ??
}
//save
SaveCity = function (item) {
City = new City(item);
$.ajax({
type: "POST",
url: "/Admin/SaveCity",
data: ko.toJSON({ City: City }),
contentType: "application/json",
success: function (result) {
if (result.Edit) {
City.CityId = result.Success;
City.CityName = item.CityName;
self.Citys.push(City);
toastr.success('City Information Save Successfully', 'Success');
}
else if (result.Edit == false) {
toastr.success('City Information Update Successfully', 'Success');
}
else {
toastr.error('There is an error please try again later', 'Errror');
}
}
});
}
//delete
DeleteCity = function (City) {
$.ajax("/Admin/DeleteCity", {
data: ko.toJSON({ CityId: City.CityId }),
type: "POST", contentType: "application/json",
success: function (result) {
if (result.Success) {
self.Citys.remove(City);
toastr.success('City Remove Successfully', 'Success');
}
else {
alert("Error..");
}
}
});
}
}
(function () {
ko.applyBindings(new CityViewModel, document.getElementById("Citys"));
loadCitys();
});
And my Html codes are
<table class="table table-striped">
<thead>
<tr>
<th>City Id</th>
<th>City Name</th>
<th></th>
<th></th>
</tr>
</thead>
<tbody data-bind="foreach: $root.Citys">
<tr data-bind="click: selectCity">
<td><span data-bind="text:CityId"></span></td>
<td><span data-bind="text:CityName"></span></td>
<td><button data-bind="click: EditCity" class="btn btn-primary">Edit</button></td>
<td><button data-bind="click: DeleteCity" class="btn btn-danger">Delete</button></td>
</tr>
</tbody>
</table>
<fieldset>
<legend>Add new / Edit City</legend>
<label>City name</label>
<input type="hidden" data-bind="value: CityId" />
<input type="text" data-bind="value: CityName" placeholder="Type city nameā€¦">
<button type="submit" data-bind="click: SaveCity" class="btn">Submit</button>
</fieldset>
With this codes I can get data form database display them successfully in my view file,
I delete the data from database, and I also can Insert data to database but here is a problem I can save data only 1st time when I change the textbox value (without page refresh) and try to save city information then it say (in Firebug on my javascript code):
TypeError: City is not a constructor
City = new City(item);
My question is what have I done wrong in this codes, and I am trying to fill the textbox and the hidden field when edit button click, how can I do this?
Thanks in advance.
There are a number of faults with your javascript, including:
The methods on your viewmodel, such as SaveCity, DeleteCity, EditCity are all being defined without the 'this/self' prefixes, therefore they are being added to the global namespace.
In your SaveCity method, your are assigning a new instance of the City class to a variable called 'City', therefore destroying the City class. It will work the first time, but any other attempts to create an instance of a City will yield an exception.
Anyway, this should be a working version of your script and HTML without the ajax stuff. You will need to adapt that yourself. I have also created a working JsFiddle here..
function City(data) {
this.CityId = ko.observable(data.CityId);
this.CityName = ko.observable(data.CityName);
}
function CityViewModel() {
var self = this;
self.Citys = ko.observableArray([]);
self.SelectedCity = ko.observable();
self.EditingCity = ko.observable(new City({CityId: null, CityName: ''}));
self.EditCity = function(city){
self.EditingCity(new City(ko.toJSON(city)));
};
//load
self.loadCitys = function () {
self.Citys().push(new City({CityId: '1245', CityName: 'Los Angeles'}));
self.Citys().push(new City({CityId: '45678', CityName: 'San Diego'}));
};
//save
self.SaveCity = function () {
var city = self.EditingCity();
if(city.CityId()){
var cityIndex;
for(var i = 0; i < self.Citys().length; i++) {
if(self.Citys()[i].CityId() === city.CityId()) {
cityIndex = i;
break;
}
}
self.Citys[cityIndex] = city;
}
else{
city.CityId(Math.floor((Math.random()*1000000)+1));
self.Citys.push(city);
}
self.EditingCity(new City({CityId: null, CityName: ''}));
}
//delete
self.DeleteCity = function (city) {
self.Citys.remove(city);
};
}
var viewModel = new CityViewModel();
viewModel.loadCitys();
ko.applyBindings(viewModel, document.getElementById("Citys"));
HTML
<table class="table table-striped">
<thead>
<tr>
<th>City Id</th>
<th>City Name</th>
<th></th>
<th></th>
</tr>
</thead>
<tbody data-bind="foreach: Citys">
<tr data-bind="click: $root.SelectedCity">
<td><span data-bind="text:CityId"></span></td>
<td><span data-bind="text:CityName"></span></td>
<td><button data-bind="click: $root.EditCity" class="btn btn-primary">Edit</button></td>
<td><button data-bind="click: $root.DeleteCity" class="btn btn-danger">Delete</button></td>
</tr>
</tbody>
</table>
<fieldset data-bind='with:EditingCity'>
<legend>Add new / Edit City</legend>
<label>City name</label>
<input type="hidden" data-bind="value: CityId" />
<input type="text" data-bind="value: CityName" placeholder="Type city name" />
<button type="submit" data-bind="click: $root.SaveCity" class="btn">Submit</button>
</fieldset>

entityAspect.setDeleted doesn't fire the subscribed propertyChanged event

I am running into problem where i subscribe to propertyChanged event, the subscribed event does fire for entity Modification, but never fires for when setting entity to Deleted.
what might i be doing wrong.
The objective of what i am doing is that, whenever user modifies the row, i want to provide
button at row level to cancel the changes. similarly when user deletes a row, i want to provide a button to unDelete a row. The modification part works as expected, but for Delete it is not working.
I was Expecting that item.entityAspect.setDeleted(), would fire the propertyChanged Event
so that i can update the vlaue of observable IsDeleted,which in turn would update the visibility of the button.
ViewModel
/// <reference path="jquery-1.8.3.js" />
/// <reference path="../linq-vsdoc.js" />
/// <reference path="../linq.min.js" />
/// <reference path="../breeze.intellisense.js" />
/// <reference path="../breeze.debug.js" />
$(document).ready(function () {
//extend country type
var Country = function () {
console.log("Country initialized");
var self = this;
self.Country_ID = ko.observable(0); // default FirstName
self.Country_Code = ko.observable(""); // default LastName
self.Country_Name = ko.observable("");
self.entityState = ko.observable("");
self.hasValidationErrors = ko.observable(false);
self.IsDeleted = ko.observable(false);
self.IsModified = ko.observable(false);
self.templateName = ko.observable("AlwayEditable");
var onChange = function () {
var hasError = self.entityAspect.getValidationErrors().length > 0;
if (hasError)
self.hasValidationErrors(true);
else
self.hasValidationErrors(false);
};
//dummy property to wireup event
//should not be used for any other purpose
self.hasError = ko.computed(
{
read: function () {
self.entityAspect // ... and when errors collection changes
.validationErrorsChanged.subscribe(onChange);
},
// required because entityAspect property will not be available till Query
// return some data
deferEvaluation: true
});
//dummy property to wireupEvent and updated self.entityStateChanged property
self.entityStateChanged = ko.computed({
read: function () {
self.entityAspect.propertyChanged.subscribe(function (changeArgs) {
if (changeArgs.entity.entityAspect.entityState.name == "Deleted") {
self.IsDeleted(false);
}
else if (changeArgs.entity.entityAspect.entityState.name == "Modified")
self.IsModified(true);
}); //subscribe
},
deferEvaluation: true,
// self.entityStateChanged(false)
});
self.fullName = ko.computed(
function () {
return self.Country_Code() + " --- " + self.Country_Name();
});
};
manager.metadataStore.registerEntityTypeCtor("Country", Country);
var countryViewModel = function (manager) {
var self = this;
window.viewModel = self;
self.list = ko.observableArray([]);
self.pageSize = ko.observable(2);
self.pageIndex = ko.observable(0);
self.selectedItem = ko.observable();
self.hasChanges = ko.observable(false);
self.totalRows = ko.observable(0);
self.totalServerRows = ko.observable(0);
self.RowsModified = ko.observable(false);
self.RowsAdded = ko.observable(false);
self.RowsDeleted = ko.observable(false);
self.templateToUse = function (dataItem, context) {
var item = dataItem;
if (!_itemTemplate) {
_itemTemplate = ko.computed(function (item) {
//var x = this;
if (this.entityAspect == "undefined")
return this.templateName("AlwayEditable");
if (this.entityAspect.entityState.name == "Deleted") {
this.templateName("readOnlyTmpl");
return this.templateName();
}
else {
this.templateName("AlwayEditable");
return this.templateName();
}
}, item);
}
if (item.entityAspect.entityState.name == "Deleted") {
item.templateName("readOnlyTmpl");
return item.templateName();
}
else {
item.templateName("AlwayEditable");
return item.templateName();
}
// return _itemTemplate();
}
var _itemTemplate;
self.hasError = ko.computed(
{
read: function () {
self.entityAspect // ... and when errors collection changes
.validationErrorsChanged.subscribe(onChange);
},
// required because entityAspect property will not be available till Query
// return some data
deferEvaluation: true
});
self.acceptChanges = function (item) {
// self.selectedItem().entityAspect.acceptChanges();
self.selectedItem(null);
}
manager.hasChanges.subscribe(function (newvalue) {
self.hasChanges(newvalue.hasChanges);
});
self.edit = function (item, element) {
highlightRow(element.currentTarget, item);
self.selectedItem(item);
};
self.discardChanges = function () {
manager.rejectChanges();
manager.clear();
self.pageIndex(0);
self.loadData();
};
self.cancel = function (item, element) {
item.entityAspect.rejectChanges();
self.selectedItem(null);
};
self.add = function () {
var countryType = manager.metadataStore.getEntityType("Country"); // [1]
var newCountry = countryType.createEntity(); // [2]
//if not using this line, the table is not updated to show this newly added item
self.list.push(newCountry);
manager.addEntity(newCountry); // [3]
self.selectedItem(newCountry);
};
self.remove = function (item) {
item.entityAspect.rejectChanges();
item.entityAspect.setDeleted(); //was expecting that propertychaged subscribe event will fire, but it does not
item.templateName("readOnlyTmpl"); //if i don't do this the template is not changed/updated
item.IsDeleted(true); //have to use this
};
self.UndoDelete = function (item) {
item.entityAspect.rejectChanges();
item.templateName("AlwayEditable");
item.IsDeleted(false);
};
self.save = function () {
if (manager.hasChanges()) {
alertTimerId = setTimeout(function () {
//this works as well
$.blockUI({ message: '<img src="Images/360.gif" /> </p><h1>Please Saving Changes</h1>', css: { width: '275px' } });
}, 700);
manager.saveChanges()
.then(saveSucceeded(alertTimerId))
.fail(saveFailed);
} else {
$.pnotify({
title: 'Save Changes',
text: "Nothing to save"
});
// alert("Nothing to save");
};
};
manager.hasChanges.subscribe(function (newvalue) {
self.hasChanges(newvalue.hasChanges);
});
manager.entityChanged.subscribe(function (changeArg) {
self.RowsDeleted(manager.getEntities(null, [breeze.EntityState.Deleted]).length);
self.RowsModified(manager.getEntities(null, [breeze.EntityState.Modified]).length);
self.RowsAdded(manager.getEntities(null, [breeze.EntityState.Added]).length);
});
//we want maxPageIndex to be recalculated as soon as totalRows or pageSize changes
self.maxPageIndex = ko.dependentObservable(function () {
return Math.ceil(self.totalRows() / self.pageSize()) - 1;
//return Math.ceil(self.list().length / self.pageSize()) - 1;
});
self.previousPage = function () {
if (self.pageIndex() > 1) {
self.pageIndex(self.pageIndex() - 1);
//self.loadData();
getData();
}
};
self.nextPage = function () {
if (self.pageIndex() < self.maxPageIndex()) {
self.pageIndex(self.pageIndex() + 1);
// self.loadData();
getData();
}
};
self.allPages = ko.dependentObservable(function () {
var pages = [];
for (i = 0; i <= self.maxPageIndex() ; i++) {
pages.push({ pageNumber: (i + 1) });
}
return pages;
});
self.moveToPage = function (index) {
self.pageIndex(index);
//self.loadData();
getData();
};
};
// self.loadData
var vm = new countryViewModel(manager);
//ko.validation.group(vm);
ko.applyBindings(vm);
// ko.applyBindingsWithValidation(vm);
vm.loadData();
try {
} catch (e) {
displayModalMessage("Page Error :- Reload the Page", e.message);
}
}); //end document.ready
View
<p><a class="btn btn-primary" data-bind="click: $root.add" href="#" title="Add New Country"><i class="icon-plus"></i> Add Country</a></p>
<span> Search Country Code :</span><input id="txtSearch" type="text" /><input id="BtnSearch" type="button" value="Search" data-bind="click: $root.loadData" />
<!--<table class="table table-striped table-bordered " style="width: 700px">-->
<!--<table id="myTable" class="ui-widget" style="width: 800px">-->
<table id="myTable" class="table table-striped table-bordered " style="width: 1200px">
<caption> <div>
<span class="label label-info">Number of Rows Added </span> <span class="badge badge-info" data-bind="text: RowsAdded"></span> ,
<span class="label label-success">Number of Rows Modified</span> <span class="badge badge-success" data-bind="text: RowsModified"></span> ,
<span class="label label-important">Number of Rows Deleted</span> <span class="badge badge-important" data-bind="text: RowsDeleted"></span>
<p/>
</div></caption>
<thead class="ui-widget-header">
<tr>
<th>Code</th>
<th>Name</th>
<th>Full Name</th>
<th />
</tr>
</thead>
<!--<tbody data-bind=" title:ko.computed(function() { debugger; }), template:{name:templateToUse, foreach: list, afterRender: HighlightRows }" class="ui-widget-content"></tbody>-->
<tbody data-bind=" title:ko.computed(function() { debugger; }), template:{name:templateToUse, foreach: list}" ></tbody>
</table>
<div class="pagination">
<ul><li data-bind="css: { disabled: pageIndex() === 0 }">Previous</li></ul>
<ul data-bind="foreach: allPages">
<li data-bind="css: { active: $data.pageNumber === ($root.pageIndex() + 1) }"></li>
</ul>
<ul><li data-bind="css: { disabled: pageIndex() === maxPageIndex() }">Next</li></ul>
</div>
<!--<input id="Button1" type="button" value="Save" data-bind="attr: { disabled: !hasChanges()}, click:saveChanges" />-->
<a class="btn btn-success btn-primary" data-bind="click: $root.save, css: { disabled: !$root.hasChanges()}" href="#" title="Save Changes"> Save Changes</a>
<!-- <input id="Button3" type="button" value="Create New" data-bind="click:AddNewCountry" />
<input id="Button4" type="button" value="Discard and reload data" data-bind="click:discardreload, attr: { disabled: !hasChanges()}" /> -->
<a class="btn btn-danger btn-primary" data-bind="click: $root.discardChanges, css: { disabled: !$root.hasChanges()}" href="#" title="Discard Changes"><i class="icon-refresh"></i> Discard & Reload</a>
<script id="readOnlyTmpl" type="text/html">
<tr >
<td>
<span class="label " data-bind="text: Country_Code "></span>
<div data-bind="if: hasValidationErrors">
<span class="label label-important" data-bind="text: $data.entityAspect.getValidationErrors('Country_Code')[0].errorMessage ">Important</span>
</div>
</td>
<td>
<span class="label " data-bind="text: Country_Name "></span>
<p data-bind="validationMessage: Country_Name"></p>
<span data-bind='visible: ko.computed(function() { debugger; }), text: Country_Name.validationMessage'> </span>
</td>
<td> <span class="label " data-bind="text: fullName "></span>
</td>
<td >
<a class="btn btn-danger" data-bind="click: $root.cancel, visible: $data.IsModified" href="#" title="cancel/undo changes">Undo Changes<i class="icon-trash"></i></a>
<a class="btn btn-danger" data-bind="click: $root.remove, visible: !$data.IsDeleted() " href="#" title="Delete this Row">Delete<i class="icon-remove"></i></a>
<a class="btn btn-danger" data-bind="click: $root.UndoDelete, visible: $data.IsDeleted() " href="#" title="Undo Delete">Un Delete<i class="icon-remove"></i></a>
</td>
</tr>
</script>
<script id="AlwayEditable" type="text/html">
<tr >
<td><input type="text" placeholder="Country Code" data-bind="value: Country_Code , uniqueName: true, css: { error: hasValidationErrors }, valueUpdate: 'afterkeydown'"/>
<!-- <div data-bind="if: $data.entityAspect.getValidationErrors().length>0">
<pre data-bind="text: $data.entityAspect.getValidationErrors('Country_Code')[0].errorMessage "></pre>
</div>-->
<div data-bind="if: hasValidationErrors">
<span class="label label-important" data-bind="text: $data.entityAspect.getValidationErrors('Country_Code')[0].errorMessage ">Important</span>
</div>
</td>
<td><input type="text" placeholder="Country Name" data-bind="value: Country_Name, uniqueName: true, valueUpdate: 'afterkeydown'"/>
<p data-bind="validationMessage: Country_Name"></p>
<span data-bind='visible: ko.computed(function() { debugger; }), text: Country_Name.validationMessage'> </span>
</td>
<td>
<span data-bind=' text: fullName'> </span>
</td>
<td >
<a class="btn btn-danger" data-bind="click: $root.cancel, visible: $data.IsModified" href="#" title="cancel/undo changes">Undo Changes<i class="icon-trash"></i></a>
<a class="btn btn-danger" data-bind="click: $root.remove, visible: !$data.IsDeleted() " href="#" title="Delete this Row">Delete<i class="icon-remove"></i></a>
<a class="btn btn-danger" data-bind="click: $root.UndoDelete, visible: $data.IsDeleted() " href="#" title="Undo Delete">Un Delete<i class="icon-remove"></i></a>
</td>
</tr>
</script>
Analysis
The propertyChanged event is raised when ... a property changes. But that's not what you want to watch. You want to monitor the entityAspect.entityState
When you set a property to a new value (for example person.FirstName("Naunihal")), you get both a propertyChanged event and a change to the entity's EntityState.
When you delete the entity, the entity's EntityState changes ... to "Deleted". But deleting doesn't change a property of the entity. Breeze does not consider the EntityState itself to be a property of the entity. Therefore, there is no propertyChanged notification.
Solution
Update Jan 12, 2013
I think more people will discover this solution if I rephrase the question that you asked so people understand that you want to listen for changes to EntityState.
So I moved my answer to a new SO question: "How can I detect a change to an entity's EntityState?". Hope you don't mind following that link.

jquery tabs not working inside dialog as partial view

I am opening a dialog with the following:
This is my Appliation Details.cshmtl
<script type="text/javascript">
$.ajaxSetup({ cache: false });
$(document).ready(function () {
$(".display tr:odd").addClass("odd");
$(".display tr:even").addClass("even");
//modal popup
$("#dialog-confirm").dialog({
autoOpen: false,
resizable: false,
height: 200,
width: 400,
modal: true,
buttons: {
"Delete": function () {
$(this).dialog("close");
$('#deleteApplication').submit();
},
Cancel: function () {
$(this).dialog("close");
}
}
});
$(".deleteLink").click(function (e) {
e.preventDefault();
$("#dialog-confirm").dialog("open");
});
$(".openDialog").live("click", function (e) {
e.preventDefault();
$("<div></div>")
.addClass("dialog")
.attr("id", $(this).attr("data-dialog-id"))
.appendTo("body")
.dialog({
title: $(this).attr("data-dialog-title"),
close: function () { $(this).remove() },
modal: true,
width: "90%",
height: "500",
buttons: {
"Close": function () {
$(this).dialog("close");
}
}
})
.load(this.href);
});
$(".close").live("click", function (e) {
e.preventDefault();
$(this).closest(".dialog").dialog("close");
});
});
</script>
<div class="tabset">
<ul class="tab_labels">
<li><span>Details</span></li>
<li><span>Versions</span></li>
<li><span>History</span></li>
<li><span>Log</span></li>
</ul>
<div class="tab_content">
<table id="detailsView" class="display">
<tbody>
<tr>
<td>#Html.LabelFor(model => model.ApplicationName)</td>
<td>#Html.DisplayFor(model => model.ApplicationName)</td>
</tr>
<tr>
<td>#Html.LabelFor(model => model.Description)</td>
<td>#Html.DisplayFor(model => model.Description)</td>
</tr>
</tbody>
</table>
</div>
<div class="tab_content">
#Html.Partial("_Versions", versions, new ViewDataDictionary {{ "applicationId", Model.ApplicationId}})
</div>
<div class="tab_content">
#Html.Partial("_RecordHistory", history)
</div>
<div class="tab_content">
#Html.Partial("_RecordLog", log)
</div>
</div>
<br />
<div class="button_wrapper_center">
<span style="white-space:nowrap;">Return to List</span>
</div>
<div id="dialog-confirm" title="Delete the item?" style="display:none" >
<p><span class="ui-icon ui-icon-alert" style="float:left; margin:0 7px 20px 0;"></span>This item will be deleted. Are you sure?</p>
</div>
The partial view _Versions contains the link to open the dialog
This is _Versions.cshtml
#model IEnumerable<WebDevelopment.SqlData.Version>
#{
var applicationId = ViewData["applicationId"];
}
<script type="text/javascript">
$(document).ready(function () {
var recordId;
$(".deleteVersionLink").click(function (e) {
e.preventDefault();
var frm = $(this);
recordId = frm.attr("id");
$("#dialog-confirmVersion").dialog("open");
});
$("#dialog-confirmVersion").dialog({
autoOpen: false,
resizable: false,
height: 200,
width: 400,
modal: true,
buttons: {
"Delete": function () {
$("#deleteVersion" + recordId).submit();
$(this).dialog("close");
},
Cancel: function () {
$(this).dialog("close");
}
}
});
$('#versions').dataTable({
"bFilter": false,
"bPaginate": false,
"bInfo": false,
"bSort": false
});
});
</script>
<table>
<tr>
<td>
<span style="white-space:nowrap;">Create New</span>
</td>
</tr>
</table>
<table cellpadding="0" cellspacing="0" border="0" class="display" id="versions">
<thead>
<tr>
<th>
#Html.LabelFor(p => Model.FirstOrDefault().VersionNumber)
</th>
<th>
#Html.LabelFor(p => Model.FirstOrDefault().ReleaseDate)
</th>
<th>
</th>
</tr>
</thead>
<tbody>
#foreach (var item in Model)
{
<tr>
<td>
#Html.ActionLink(item.VersionNumber, "Details", "Version", new { id = item.VersionId }, new { #class = "openDialog", data_dialog_id = "detailsDialog", data_dialog_title = "Version Details" })
</td>
<td>
#Html.DisplayFor(modelItem => item.ReleaseDate)
</td>
<td>
#Html.ActionLink("Edit", "Edit", "Version", new { id = item.VersionId }, null) |
#Html.ActionLink("Delete", "DeleteConfirmed", "Version", new { id = item.VersionId }, new { #class = "deleteVersionLink", #id = item.VersionId })
#using (Html.BeginForm("DeleteConfirmed", "Version", new { id = item.VersionId }, FormMethod.Post, new { #id = "deleteVersion" + item.VersionId })){}
</td>
</tr>
}
</tbody>
</table>
<div id="dialog-confirmVersion" title="Delete the item?" style="display:none" >
<p><span class="ui-icon ui-icon-alert" style="float:left; margin:0 7px 20px 0;"></span>This item will be deleted. Are you sure?</p>
</div>
Here is the Version Contoller
public ActionResult Details(int id)
{
ViewBag.History = recordHistoryRepository.GetRecordHistory("ConnectionString", "Version", id);
ViewBag.Log = recordLogRepository.GetRecordLog("ConnectionString", "Version", id);
var version = versionRepository.GetVersionById(id);
if (Request.IsAjaxRequest())
{
return PartialView("_DetailsDialog", version);
}
return View(version);
}
Here is Version Details.cshtml
#model WebDevelopment.SqlData.Version
#Html.Partial("_DetailsDialog")
Here is _DetailsDialog
#model WebDevelopment.SqlData.Version
#{
var history = ViewBag.History as IEnumerable<WebDevelopment.SqlData.RecordHistory>;
var log = ViewBag.Log as IEnumerable<WebDevelopment.SqlData.RecordLog>;
}
<table width="100%">
<tr>
<td><h1 class="first">#Html.DisplayTextFor(_ => Model.Application.ApplicationName)</h1></td>
</tr>
</table>
<div class="tabset">
<ul class="tab_labels">
<li><span>Details</span></li>
<li><span>History</span></li>
<li><span>Log</span></li>
</ul>
<div class="tab_content">
<table id="detailsDialogView" class="display">
<tbody>
<tr>
<td>#Html.LabelFor(model => model.VersionNumber)</td>
<td>#Html.DisplayFor(model => model.VersionNumber)</td>
</tr>
<tr>
<td>#Html.LabelFor(model => model.ReleaseDate)</td>
<td>#Html.DisplayFor(model => model.ReleaseDate)</td>
</tr>
</tbody>
</table>
</div>
<div class="tab_content">
#Html.Partial("_RecordHistory", history)
</div>
<div class="tab_content">
#Html.Partial("_RecordLog", log)
</div>
</div>
The dialog opens and I see the html for the _DetailsDialog page in firebug, but the tabs are not functioning. The datatables in partial views _RecordHistory and _RecordLog from _DetailsDialog.cshtml do not function as well.
I had a similar problem - and did not find a solution. I went to the easytabs plugin instead (http://os.alfajango.com/easytabs/). It works like a charm and I find easy to use and adapt.

Resources