I create ng-template and bind it with controller and this template pass through ui-bootstrap modal.
code :-
vm.uploadFile = function () {
var uploadModal = $uibModal.open({
animation: true,
templateUrl: 'upload.html',
bindToController: true,
controller: 'modalCtrl',
controllerAs: 'modalVm',
resolve: {
items: function () {
}
}
});
uploadModal.result.then(function (data) {
data.uploadedBy = 'admin';
data.fileName = data.name;
vulGridService.dataStackForFile.unshift(data);
vulGridService.gridApi.core.refresh();
}, function () {
console.log('Modal dismissed at: ' + new Date());
}
);
}
}
my template is below:-
<script type="text/ng-template" id="upload.html">
<div class="">
<form name="component" ng-submit="modalVm.upload()" novalidate>
<h4 class="margin-null modal-padding bg-primary">Upload File</h4>
<div class="modal-body">
<div class="form-group">
<label>File Type</label><br>
<div class="select-drop-down-icon">
<select ng-model="modalVm.file.fileType"
name="fileType"
class=" cover-block input-field-styling"
ng-change="modalVm.checkFile()" required>
<option value="">Select File Extension</option>
<option value="Qualys">Qualys(.xml)</option>
<option value="Nessus">Nessus(.nessus)</option>
<option value="zip">.zip</option>
</select>
</div>
</div>
<div class="form-group bottom-spacing">
<label>File To Upload</label><br>
<div class="cover-block form-control padding-null">
<input class="border-null text-field-padding" ng-model="modalVm.file.name">
<!--<file-field ng-change="modalVm.checkFile(uploadFile.name)"-->
<!--class="btn btn-primary inline-view pull-right "-->
<!--ng-model="uploadFile">-->
<!--<i class="fa fa-upload" aria-hidden="true"></i>-->
<!--Chose File-->
<!--</file-field>-->
<div class="btn btn-primary inline-view pull-right upload-field">
<i class="fa fa-upload" aria-hidden="true"></i> Chose File
<input grab-file-name get-file-name="modalVm.getFileName" type="file" class="upload">
</div>
<div class="top-space">
<span class="error-text" ng-show="modalVm.extension">
Please Select proper extension file
</span>
</div>
</div>
</div>
<div class="text-center">
<button ng-disabled="modalVm.extension" type="submit"
class="btn btn-success sharp mar-right" aria-label="Close">Save
</button>
<button type="reset" ng-click="modalVm.cancel()" data-dismiss="modal"
class="btn btn-danger sharp mar-right" aria-label="Close">Cancel
</button>
</div>
</div>
</form>
</div>
modalCtrl
function modalCtrl($uibModalInstance, toastr, dateFactory, $scope) {
var modalVm = this;
modalVm.extension = false;
console.log($scope);
modalVm.cancel = function () {
$uibModalInstance.dismiss('cancel');
};
modalVm.upload = function (data) {
// data.uploadedOn = dateFactory.getDate();
// $uibModalInstance.close(data);
// toastr.success('File is Uploaded', 'success', {closeButton: true});
};
modalVm.checkFile = function (file, fileType) {
console.log(file, fileType);
if (file) {
switch (fileType) {
case 'Nessus':
var matchNessus = /[(a-z)(A-Z)(0-9^)]+.(nessus)/g;
if (matchNessus.test(file)) {
console.log('Nessus', file);
modalVm.extension = false;
} else {
modalVm.extension = true;
}
break;
case 'Qualys':
var matchQualys = /[(a-z)(A-Z)(0-9^)]+.(xml)/g;
if (matchQualys.test(file)) {
console.log('Qualys', file);
modalVm.extension = false;
} else {
modalVm.extension = true;
}
break;
case 'zip':
var matchZip = /[(a-z)(A-Z)(0-9^)]+.(zip)/g;
if (matchZip.test(file)) {
console.log('zip', file);
modalVm.extension = false;
} else {
modalVm.extension = true;
}
break;
default:
modalVm.extension = true;
break;
}
}
};
modalVm.getFileName = function (gotFileName) {
console.log($scope.fileType);
modalVm.fileName = gotFileName;
};
}
In which input field not binding with the controller but the function is invoking, please give any hint or solution on it.
Related
I want to display in time and out time of the user in full calendar. Each and every user has different in time and out time. And the user id is selected in drop down. Right now I'm getting the drop down which is binded with the user name and user id so I have to bind the login time and logout time of the user to the calendar.This is my code where i bind the drop down with data. This is my controller code for binding the drop down with the user id and user name.
public ActionResult AttendanceScreen()
{
List<SelectListItem> userList = Getuser();
return View(userList);
}
[HttpPost]
public ActionResult AttendanceScreen(string ddlCustomers)
{
List<SelectListItem> userList = Getuser();
if (!string.IsNullOrEmpty(ddlCustomers))
{
SelectListItem selectedItem = userList.Find(p => p.Value == ddlCustomers);
ViewBag.Message = "Calender for Name: " + selectedItem.Text;
ViewBag.Message += "\\nID: " + selectedItem.Value;
}
return View(userList);
}
private static List<SelectListItem> Getuser()
{
RegMVCEntities entities = new RegMVCEntities();
List<SelectListItem> customerList = (from p in entities.tblRegistrations.AsEnumerable()
select new SelectListItem
{
Text = p.FName,
Value = p.UserId.ToString()
}).ToList();
//Add Default Item at First Position.
customerList.Insert(0, new SelectListItem { Text = "--Select Employee--", Value = "" });
return customerList;
}
This is my view for displaying the user id and user name as alert.
#using (Html.BeginForm("AttendanceScreen", "Home", FormMethod.Post))
{
#Html.DropDownList("ddlCustomers", Model)
<br />
<br />
<input type="submit" value="Submit" />
}
#if (ViewBag.Message != null)
{
<script type="text/javascript">
window.onload = function () {
alert("#ViewBag.Message");
};
For displaying the calendar the controller code is
public JsonResult GetEvents()
{
using (RegMVCEntities dc = new RegMVCEntities())
{
var events = dc.User_LogTime.ToList();
dc.Configuration.ProxyCreationEnabled = false;
dc.Configuration.LazyLoadingEnabled = false;
return new JsonResult { Data = events, JsonRequestBehavior = JsonRequestBehavior.AllowGet };
}
}
For displaying the calendar the code of my view is
<h2>Calender</h2>
<div id="calender"></div>
<div id="myModal" class="modal fade" role="dialog">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<h4 class="modal-title"><span id="eventTitle"></span></h4>
</div>
<div class="modal-body">
<button id="btnDelete" class="btn btn-default btn-sm pull-right">
<span class="glyphicon glyphicon-remove"></span> Remove
</button>
<button id="btnEdit" class="btn btn-default btn-sm pull-right" style="margin-right:5px;">
<span class="glyphicon glyphicon-pencil"></span> Edit
</button>
<p id="pDetails"></p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
<div id="myModalSave" class="modal fade" role="dialog">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<h4 class="modal-title">Save Event</h4>
</div>
<div class="modal-body">
<form class="col-md-12 form-horizontal">
<input type="hidden" id="hdEventID" value="0" />
#*<div class="form-group">
<label>Subject</label>
<input type="text" id="txtSubject" class="form-control" />
</div>*#
<div class="form-group">
<label>LoginTime</label>
<div class="input-group date" id="dtp1">
<input type="text" id="txtStart" class="form-control" />
<span class="input-group-addon">
<span class="glyphicon glyphicon-calendar"></span>
</span>
</div>
</div>
#*<div class="form-group">
<div class="checkbox">
<label><input type="checkbox" id="chkIsFullDay" checked="checked" /> Is Full Day event</label>
</div>
</div>*#
<div class="form-group" id="divEndDate" style="display:none">
<label>LogoutTime</label>
<div class="input-group date" id="dtp2">
<input type="text" id="txtEnd" class="form-control" />
<span class="input-group-addon">
<span class="glyphicon glyphicon-calendar"></span>
</span>
</div>
</div>
#*<div class="form-group">
<label>Description</label>
<textarea id="txtDescription" rows="3" class="form-control"></textarea>
</div>*#
<div class="form-group">
<label>Theme Color</label>
<select id="ddThemeColor" class="form-control">
<option value="">Default</option>
<option value="red">Red</option>
<option value="blue">Blue</option>
<option value="black">Black</option>
<option value="green">Green</option>
</select>
</div>
<button type="button" id="btnSave" class="btn btn-success">Save</button>
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</form>
</div>
</div>
</div>
</div>
<link href="//cdnjs.cloudflare.com/ajax/libs/fullcalendar/3.4.0/fullcalendar.min.css" rel="stylesheet" />
<link href="//cdnjs.cloudflare.com/ajax/libs/fullcalendar/3.4.0/fullcalendar.print.css" rel="stylesheet" media="print" />
<link href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datetimepicker/4.17.47/css/bootstrap-datetimepicker.min.css" rel="stylesheet" />
#section Scripts{
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.18.1/moment.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/fullcalendar/3.4.0/fullcalendar.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datetimepicker/4.17.47/js/bootstrap-datetimepicker.min.js"></script>
<script>
$(document).ready(function () {
debugger;
var event_array = [];
var selectedEvent = null;
FetchEventAndRenderCalendar();
function FetchEventAndRenderCalendar() {
events = [];
$.ajax({
url: "/Home/GetEvents",
data: "",
type: "GET",
dataType: "json",
async: false,
cache: false,
success: function (data) {
alert("success");
$.each(data, function (i, v) {
event_array.push({
userid: v.UserId,
start: moment(v.LoginTime),
end: moment(v.LogoutTime),
//start: moment(v.start),
//end: v.end != null ? moment(v.end) : null,
//color: v.themecolor,
//allday: v.isfullday
});
})
GenerateCalender(event_array);
},
error: function (error) {
alert('failed');
}
})
}
function GenerateCalender(event_array) {
debugger;
//$('#calender').fullCalendar('destroy');
$('#calender').fullCalendar({
contentHeight: 400,
defaultDate: new Date(),
timeFormat: 'h(:mm)a',
header: {
left: 'prev,next today',
center: 'title',
right: 'month,basicWeek,basicDay,agenda'
},
eventLimit: true,
eventColor: '#378006',
events: event_array,
eventClick: function (calEvent, jsEvent, view) {
selectedEvent = calEvent;
$('#myModal #eventTitle').text(calEvent.userid);
var $description = $('<div/>');
$description.append($('<p/>').html('<b>LoginTime:</b>' + calEvent.logintime.format("DD-MMM-YYYY HH:mm a")));
$description.append($('<p/>').html('<b>LogoutTime:</b>' + calEvent.logouttime.format("DD-MMM-YYYY HH:mm a")));
//$description.append($('<p/>').html('<b>Description:</b>' + calEvent.description));
//$('#myModal #pDetails').empty().html($description);
$('#myModal').modal();
},
//selectable: true,
//select: function (logintime, logouttime) {
// selectedEvent = {
//// userid: 0,
//// logintime: logintime,
//// logouttime: logouttime
//// };
//// openAddEditForm();
//// $('#calendar').fullCalendar('unselect');
////},
////editable: false,
eventDrop: function (event) {
var data = {
UserId: event.userid,
LoginTime: event.logintime.format('DD/MM/YYYY HH:mm A'),
LogoutTime: event.logouttime.format('DD/MM/YYYY HH:mm A')
};
SaveEvent(data);
}
});
}
this is the screenshot of my current page
The attendance screen
Right I'm just getting the in time and out time in the database as you can see in screenshot but that is for all the user in Database.I just need to update the calendar with in time and out time of the user id selected in drop down.
I have done it. It was simple I just needed to use session for getting the user id.This is my code:
public ActionResult AttendanceScreen(string ddlCustomers)
{
Session["userid"] = ddlCustomers;
List<SelectListItem> userList = Getuser();
if (!string.IsNullOrEmpty(ddlCustomers))
{
SelectListItem selectedItem = userList.Find(p => p.Value == ddlCustomers);
ViewBag.Message = "Calender for Name: " + selectedItem.Text;
ViewBag.Message += "\\nID: " + selectedItem.Value;
}
return View(userList);
// return RedirectToAction("Index", "Nome", new { userid: userid });
}
public JsonResult GetEvents()
{
string username = User.Identity.Name;
int isessionid = Convert.ToInt32(Session["userid"]);
List<SelectListItem> userList = Getuser();
if (isessionid == 0)
{
return null;
}
else
{
//int userid = int.Parse(username);
RegMVCEntities svc = new RegMVCEntities();
svc.Configuration.ProxyCreationEnabled = false;
svc.Configuration.LazyLoadingEnabled = false;
// var oCampaigns = svc.User_LogTime;
var oReturn =
(from c in svc.User_LogTime.AsEnumerable()
where c.UserId == isessionid
select new
{
LoginTime = c.LoginTime,
Logouttime = c.LogoutTime
}).ToList();
//var events = dc.User_LogTime.ToList();
//dc.Configuration.ProxyCreationEnabled = false;
// dc.Configuration.LazyLoadingEnabled = false;
return new JsonResult { Data = oReturn.ToList(), JsonRequestBehavior = JsonRequestBehavior.AllowGet };
}
}
This is how I am using the component and sending the parameters using a Custom Element:
<div class="container" data-bind="with: DevoteeList">
<div class="row" style="padding: 10px;">
<div class="col-md-8"></div>
<div class="col-md-4">
<ko-pager params="Data: Devotees,
Modifier: $parent.DevoteeModifier,
PageCount: DevoteesPageCount(),
Url: '#Url.Action("SelectDevotees", "Devotee", new { a = 1 })'"></ko-pager>
</div>
</div>
This is how I am defining a Knockout Component. It is a Pager that I want to use at few places. But, I am receiving the error: Uncaught Error: Unable to process binding "with: function (){return SelectDevotees }"
Message: Unable to process binding "with: function (){return DevoteeList }"
Message: Unable to process binding "component: function () { return l }"
Message: Component 'ko-pager': Unknown template value: [object Object]
ko.components.register('ko-pager', {
viewModel: function (params) {
var self = this;
self.currentPage = ko.observable(1);
self.pages = ko.observableArray([]);
self.PageCount = ko.observable(params.PageCount);
//self.currentPage.subscribe(function (nv) {
// self.GetPage(self.parent);
//});
self.GetPages = function () {
for (var i = 1; i <= params.PageCount ; i++) {
self.pages.push(i);
}
return self.pages;
};
self.FirstPage = function () {
self.GetPage(1);
};
self.PrevPage = function () {
if (self.currentPage() > 1) {
var pn = self.currentPage() - 1;
self.GetPage(pn);
}
};
self.LastPage = function () {
self.GetPage(params.PageCount);
};
self.NextPage = function () {
if (self.currentPage() < params.PageCount) {
var pn = self.currentPage() + 1;
self.GetPage(pn);
}
};
self.GetPage = function (pg) {
if (pg == null)
pg = self.currentPage();
else
self.currentPage(pg);
var url = params.Url + '&pageNumber=' + pg;
$.get(url, function (data) {
var t = ko.mapping.fromJS(data);
if (params.Modifier) {
params.Modifier(t);
}
params.Data(t());
});
};
},
template: { element: document.getElementById('ko-ajax-pager') }
});
<div id="ko-ajax-pager" style="display: none;">
<div class="row" style="padding: 10px;" data-bind="visible: PageCount > 1">
<div class="col-md-1"></div>
<div class="col-md-2">
<input type="button" value="First" class="btn" data-bind="click: FirstPage" />
</div>
<div class="col-md-2">
<input type="button" value="Prev" class="btn" data-bind="click: PrevPage" />
</div>
<div class="col-md-2">
<select data-bind="options: GetPages(), value: currentPage, event: { change: GetPage(null) }">
</select>
</div>
<div class="col-md-2">
<input type="button" value="Next" class="btn" data-bind="click: NextPage" />
</div>
<div class="col-md-2">
<input type="button" value="Last" class="btn" data-bind="click: LastPage" />
</div>
<div class="col-md-1"></div>
</div>
</div>
Can someone please figure out, what is wrong?
I have a problem with an AngularJS app I'm making. It shows a list of contacts, and for each contact there is a button whereupon clicking the button a modal pops up with a form. This form should show the existing contact information, and if you want to change something you type the new information and press submit.
The problem, however, is that the existing information is not shown in the form, hence editing it doesn't work. I imagine that the issue is that the modal does not inherit the scope from the parent page, but I don't know what to do in order to fix that. I have tried playing around with the attributes on the input fields (for example prepending ng-model by $parent. and defining an ng-init value), but to no avail, so I hope some of the experts here will be able to point me on the right track.
Thank you in advance.
Now let me show you my code, so you can see the context I'm talking about. Here is the html that displays the list of contacts:
<div class="panel panel-default" ng-controller="contactsController">
<div class="panel-body">
<div id="gridContainer" ng-class="{'': state == 'list', 'none': state != 'list'}">
<table class="table table-bordered table-striped">
<thead>
<tr>
<th scope="col"><spring:message code="contacts.name"/></th>
<th scope="col"><spring:message code="contacts.email"/></th>
<th scope="col"><spring:message code="contacts.phone"/></th>
<th scope="col"></th>
</tr>
</thead>
<tbody>
<tr ng-repeat="contact in page.source">
<td class="tdContactsCentered">{{contact.name}}</td>
<td class="tdContactsCentered">{{contact.email}}</td>
<td class="tdContactsCentered">{{contact.phoneNumber}}</td>
<td class="width15">
<div class="text-center">
<input type="hidden" value="{{contact.id}}"/>
<a ng-href="#updateContactsModal"
ng-click="selectedContact(contact);"
role="button"
title="<spring:message code="update"/> <spring:message code="contact"/>"
class="btn btn-sm btn-warning" data-toggle="modal">
<i class="icon-pencil"></i>
</a>
<a ng-href="#deleteContactsModal"
ng-click="selectedContact(contact);"
role="button"
title="<spring:message code="delete"/> <spring:message code="contact"/>"
class="btn btn-sm btn-danger" data-toggle="modal">
<em class="fa fa-trash"></em>
</a>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
And the html that defines the modal and the form:
<div id="updateContactsModal"
class="modal fade centering"
role="dialog"
aria-labelledby="updateContactsModalLabel"
aria-hidden="true" style="display: none;">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
<h3 id="updateContactsModalLabel" class="modal-title">
<spring:message code="update"/> <spring:message code="contact"/>
</h3>
</div>
<div class="modal-body" data-ng-controller="contactsController">
<form name="updateContactForm" novalidate>
<input type="hidden"
required
data-ng-model="contact.id"
name="id"
value="{{contact.id}}"/>
<div>
<div class="form-group">
<label>* <spring:message code="contacts.name"/>:</label>
<input type="text"
autofocus
required
class="form-control"
data-ng-model="contact.name"
name="name"
placeholder="<spring:message code='contact'/> <spring:message code='contacts.name'/> "/>
<div>
<span class="alert alert-error"
ng-show="displayValidationError && updateContactForm.name.$error.required">
<spring:message code="required"/>
</span>
</div>
</div>
<div class="form-group">
<label>* <spring:message code="contacts.email"/>:</label>
<div class="input-append">
<input type="text"
required
class="form-control"
ng-model="contact.email"
name="email"
placeholder="<spring:message code='sample.email'/> "/>
</div>
<div>
<span class="alert alert-error"
ng-show="displayValidationError && updateContactForm.email.$error.required">
<spring:message code="required"/>
</span>
</div>
</div>
<div class="form-group">
<label>* <spring:message code="contacts.phone"/>:</label>
<div class="input-append">
<input type="text"
required
class="form-control"
ng-model="contact.phoneNumber"
name="phoneNumber"
placeholder="<spring:message code='sample.phone'/> "/>
</div>
<div>
<span class="alert alert-error"
ng-show="displayValidationError && updateContactForm.phoneNumber.$error.required">
<spring:message code="required"/>
</span>
</div>
</div>
</div>
</form>
<div class="modal-footer">
<input type="submit"
class="btn btn-primary"
ng-click="updateContact(updateContactForm);"
value='<spring:message code="update"/>'/>
<button class="btn btn-default"
data-dismiss="modal"
ng-click="exit('#updateContactsModal');"
aria-hidden="true">
<spring:message code="cancel"/></button>
</div>
</div>
<span class="alert alert-error dialogErrorMessage"
ng-show="errorOnSubmit">
<spring:message code="request.error"/>
</span>
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
And finally the relevant parts of the controller:
App.controller('contactsController', ["$scope", "$http", function($scope,$http) {
$scope.pageToGet = 0;
$scope.state = 'busy';
$scope.lastAction = '';
$scope.url = "/uaiContacts/protected/contacts/";
$scope.errorOnSubmit = true;
$scope.errorIllegalAccess = false;
$scope.displayMessageToUser = false;
$scope.displayValidationError = false;
$scope.displaySearchMessage = false;
$scope.displaySearchButton = false;
$scope.displayCreateContactButton = false;
$scope.contact = {};
$scope.searchFor = "";
$scope.getContactList = function () {
var url = $scope.url;
$scope.lastAction = 'list';
$scope.startDialogAjaxRequest();
var config = {params: {page: $scope.pageToGet}};
$http.get(url, config)
.success(function (data) {
$scope.finishAjaxCallOnSuccess(data, null, false);
})
.error(function () {
$scope.state = 'error';
$scope.displayCreateContactButton = false;
});
};
$scope.populateTable = function (data) {
if (data.pagesCount > 0) {
$scope.state = 'list';
$scope.page = {source: data.contacts, currentPage: $scope.pageToGet, pagesCount: data.pagesCount, totalContacts : data.totalContacts};
if($scope.page.pagesCount <= $scope.page.currentPage){
$scope.pageToGet = $scope.page.pagesCount - 1;
$scope.page.currentPage = $scope.page.pagesCount - 1;
}
$scope.displayCreateContactButton = true;
$scope.displaySearchButton = true;
} else {
$scope.state = 'noresult';
$scope.displayCreateContactButton = true;
if(!$scope.searchFor){
$scope.displaySearchButton = false;
}
}
if (data.actionMessage || data.searchMessage) {
$scope.displayMessageToUser = $scope.lastAction != 'search';
$scope.page.actionMessage = data.actionMessage;
$scope.page.searchMessage = data.searchMessage;
} else {
$scope.displayMessageToUser = false;
}
};
$scope.exit = function (modalId) {
$(modalId).modal('hide');
$scope.contact = {};
$scope.errorOnSubmit = false;
$scope.errorIllegalAccess = false;
$scope.displayValidationError = false;
};
$scope.finishAjaxCallOnSuccess = function (data, modalId, isPagination) {
$scope.populateTable(data);
$("#loadingModal").modal('hide');
if(!isPagination){
if(modalId){
$scope.exit(modalId);
}
}
$scope.lastAction = '';
};
$scope.startDialogAjaxRequest = function () {
$scope.displayValidationError = false;
$("#loadingModal").modal('show');
$scope.previousState = $scope.state;
$scope.state = 'busy';
};
$scope.handleErrorInDialogs = function (status) {
$("#loadingModal").modal('hide');
$scope.state = $scope.previousState;
// illegal access
if(status == 403){
$scope.errorIllegalAccess = true;
return;
}
$scope.errorOnSubmit = true;
$scope.lastAction = '';
};
$scope.addSearchParametersIfNeeded = function(config, isPagination) {
if(!config.params){
config.params = {};
}
config.params.page = $scope.pageToGet;
if($scope.searchFor){
config.params.searchFor = $scope.searchFor;
}
};
$scope.selectedContact = function (contact) {
$scope.contact = angular.copy(contact);
debugger;
};
$scope.updateContact = function (updateContactForm) {
if (!updateContactForm.$valid) {
debugger;
$scope.displayValidationError = true;
return;
}
$scope.lastAction = 'update';
var url = $scope.url + $scope.contact.id;
$scope.startDialogAjaxRequest();
var config = {};
$scope.addSearchParametersIfNeeded(config, false);
$http.put(url, $scope.contact, config)
.success(function (data) {
$scope.finishAjaxCallOnSuccess(data, "#updateContactsModal", false);
})
.error(function(data, status, headers, config) {
$scope.handleErrorInDialogs(status);
});
};
$scope.getContactList();
}]);
The modal doesn't share the same scope as the contacts table because each time Angular finds another ng-controller directive, it creates a new scope.
You're declaring ng-scope in both the contacts table and the modal, which causes angular to create different scopes.
See this answer for more details:
https://stackoverflow.com/a/14462341/4938335
There are a few ways to solve this...
1) Put the modal HTML inside the parent element where you're already declaring ng-controller the first time - that way it will be part of the same scope
2) Use UI Bootstrap's modal directive to generate the modal with its own controller and pass in $scope.contact from your contactsController. See example here https://angular-ui.github.io/bootstrap/#/modal
3) Create a service that stores $scope.contact and inject that into a separate controller that you create for the modal. Here's someone else's fiddle that shows this:
http://jsfiddle.net/whnSs/
I am trying to get data FROM modal to invoking controller, and all the examples I have found only describe way to get data to modal.
What is the proper way to do it?
This is a form I am using in modal:
<form class="form-horizontal">
<div class="modal-body">
<div class="control-group">
<label class="control-label">Name:</label>
<div class="controls">
<input type="text" ng-model="transaction.name" placeholder="Transaction name" />
</div>
</div>
<div class="control-group">
<label class="control-label">Category</label>
<div class="controls">
<input type="text" ng-model="transaction.category" placeholder="Category" />
</div>
</div>
<div class="control-group">
<label class="control-label">Amount</label>
<div class="controls">
<input type="text" ng-model="transaction.amount" placeholder="Amount" />
</div>
</div>
<div class="control-group">
<label class="control-label">Date</label>
<div class="controls">
<input type="text" datepicker-popup="dd-MMMM-yyyy" ng-model="transaction.date" is-open="opened" min="minDate" max="'2015-06-22'" datepicker-options="dateOptions" date-disabled="disabled(date, mode)" ng-required="true" />
<button class="btn" ng-click="open()"><i class="icon-calendar"></i></button>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn pull-left" data-dismiss="modal">
<i class="icon-remove"></i> Cancel
</button>
<button type="submit" class="btn btn-primary" ng-disabled="pwError || incomplete" data-dismiss="modal" ng-click="createTransaction()">
<i class="icon-ok icon-white"></i> Save Changes
</button>
</div>
These are controllers:
moneyApp.controller("TransactionController", function($scope, $http, $modal, $log) {
console.log("modal: ", $modal);
$scope.transaction = {}
$scope.open = function() {
var modalInstance = $modal.open({
templateUrl: 'partials/modal.html',
controller: 'ModalInstanceController',
resolve: {
transaction: function() {
return $scope.transaction;
}
}
});
modalInstance.result.then(function (receivedTransaction) {
$scope.selected = receivedTransaction;
console.log("Transaction received: ", transaction);
}, function () {
$log.info('Modal dismissed at: ' + new Date());
});
};
$http({method: 'GET', url: 'transactions/15/all/'}).success(function(data) {
$scope.transactions = data; // response data
});
})
and
moneyApp.controller("ModalInstanceController", function($scope, $modalInstance, $http, transaction) {
$scope.createTransaction = function() {
console.log("Transakcja: ", $scope.transaction);
$scope.transaction.budgetId = 15;
$scope.selected = {
item: $scope.transaction
}
$http({method: 'POST', url: 'transactions/add/', data : $scope.transaction, headers:{'Accept': 'application/json', 'Content-Type': 'application/json; ; charset=UTF-8'}}).success(function(data) {
console.log("Transaction succesfully added to a DB...");
});
}
$scope.ok = function () {
$modalInstance.close($scope.selected.item);
};
$scope.cancel = function () {
$modalInstance.dismiss('cancel');
};
});
When I am trying to invoke method createTransaction, $scope.transaction is undefined. How to get data from this form?
I think you need to assign transaction to $scope.transaction in your ModalInstanceController because you are passing in the transaction object but not putting it into $scope.
$scope.transaction = transaction
In your Modal form you need to pass the ng-model object(ie transaction) to the function (createTransaction()) which gets called on form submit.
<button type="submit" class="btn btn-primary" ng-disabled="pwError || incomplete" data-dismiss="modal" ng-click="createTransaction(transaction)">
<i class="icon-ok icon-white"></i> Save Changes
</button>
And in your controller add the object as parameter to the java-script function.
$scope.createTransaction = function(transaction) {
console.log("transaction details: "+ transaction.category+" "+transaction.amount);
};
Let me know if you are facing any issues, i can share the working code of mine.
I'm using knockoutjs for the first time in an attempt to have a list of tasks and then to be able to click on one to show it in a popup form. The issue I'm having is with data-bind="click: $parent.edit", which calls ToDoListViewModel/edit.
When I first started writing the list code, it would pass in the current row's todo object as the first parameter into the edit function. After adding the second view model for my add/edit popup form, it no longer behaves this way. Calling $parent.edit still calls the edit function, however now it passes in an empty object { }.
It seems like I'm running into some sort of conflicting bindings issue, any ideas?
Here is the to do list html:
<table class="table table-striped table-hover" data-bind="visible: isVisible">
<thead>
<tr>
<th>To-Do</th>
<th>Estimate</th>
<th>Deadline</th>
#if (Model == null) { <th>Property</th> }
<th>Tenant</th>
<th style="display: none;">Assigned To</th>
<th></th>
</tr>
</thead>
<tbody data-bind="foreach: todos">
<tr data-bind="visible: isVisible()">
<td><a class="pointer" title="Edit To-Do" data-bind="click: $parent.edit, text: Task"></a></td>
<td data-bind="text: FormattedAmount"></td>
<td data-bind="text: FormattedDueDate"></td>
<td data-bind="visible: $parent.showPropertyColumn, text: PropertyName"></td>
<td data-bind="text: TenantName"></td>
<td>
<div class="btn-group pull-right">
<a class="btn btn-primary pointer default-click-action" data-bind="click: $parent.markComplete">Mark Complete</a>
<button class="btn btn-primary dropdown-toggle" data-toggle="dropdown"><span class="caret"></span></button>
<ul class="dropdown-menu">
<li><a class="pointer" data-bind="click: $parent.edit">Edit To-Do</a></li>
<li><a class="pointer" data-bind="click: $parent.remove">Delete To-Do</a></li>
</ul>
</div>
</td>
</tr>
</tbody>
</table>
And here is the popup html:
#model Housters.Schemas.Models.Property.Listing
<div id="popup" class="modal fade" style="display: none;" data-bind="with: form">
#using (Html.BeginForm("SaveTodo", "Properties", FormMethod.Post, new { Id = "form", #class = "form-horizontal" }))
{
<div class="modal-header">
<a class="close" data-dismiss="modal">×</a>
<h3>To-Do Information</h3>
</div>
<div class="modal-body">
<input id="id" name="id" type="hidden" data-bind="value: todo().Id" />
<input id="originalListingId" type="hidden" value="#(Model != null ? Model.IdString : "")" />
<div class="control-group #(Model != null ? " hide" : "")">
<label class="control-label" for="listingId">Property</label>
<div class="controls">
#Html.DropDownList("listingId", ViewBag.Listings as SelectList, "None",
new Dictionary<string, Object> { { "data-bind", "value: todo().ListingId" } })
</div>
</div>
<div class="control-group">
<label class="control-label" for="tenantId">Tenant</label>
<div class="controls">
<select id="tenantId" name="tenantId" class="span11" data-bind="value: todo().TenantId">
<option value="">None</option>
</select>
<p class="help-block">Is this task related to a certain tenant?</p>
</div>
</div>
<div class="control-group">
<label class="control-label" for="amount">Estimate to Complete</label>
<div class="controls">
<div class="input-prepend"><span class="add-on">$</span><input type="text" id="amount" name="todo.Amount" maxlength="10"
class="span11 number" data-bind="value: todo().Amount" /></div>
</div>
</div>
<div class="control-group">
<label class="control-label" for="dueDate">Due Date</label>
<div class="controls">
<input type="text" id="dueDate" name="todo.DueDate" maxlength="10"
class="span11 date" data-bind="value: todo().DueDate" />
</div>
</div>
<div class="control-group">
<label class="control-label" for="task">Task<span class="required-asterisk">*</span></label>
<div class="controls">
<textarea id="task" name="todo.Task" rows="4" class="span11 required" data-bind="value: todo().Task"></textarea>
</div>
</div>
</div>
<div class="modal-footer">
<a class="btn pointer" data-dismiss="modal">Close</a>
<a id="mark-complete-popup" class="btn btn-primary" data-dismiss="modal" data-bind="visible: (todo().Id && !todo().IsComplete), click: markComplete">Mark Complete</a>
<button type="button" class="btn btn-primary" data-bind="click: save">Save</button>
</div>
}
</div>
And lastly, here is the javascript defining the view models:
function ToDoList () {
if(!(this instanceof arguments.callee))
return new arguments.callee();
var parent = this;
this.showCompleted = ko.observable(false);
this.tenantFilter = new PropertyTenantFilter();
this.viewModel = {
list: new ToDoListViewModel(),
form: new ToDoFormViewModel()
};
this.init = function () {
//get all tenants.
utils.block($("#grid-content"), "Loading");
this.tenantFilter.init(function () {
//initialize view model.
ko.applyBindings(this.viewModel);
//setup controls & events.
$("#dueDate").datepicker();
$("#listingId").change(this.tenantFilter.getByListing.bind(this.tenantFilter)).change();
} .bind(this));
};
function ToDoListViewModel() {
//init.
var self = this;
self.todos = ko.observableArray([]);
//computed.
self.showPropertyColumn = ko.computed(function () {
return $("#originalListingId").val().length == 0;
});
self.isVisible = ko.computed(function () {
return _.find(self.todos(), function (todo) { return todo.isVisible(); }) != null;
});
//operations.
self.add = function () {
//set form field values.
parent.viewModel.form.fill(new schemas.ToDo({}, parent));
//show popup.
$("#popup").modal("show");
};
self.edit = function (todo) {
console.debug("edit: " + JSON.stringify(todo));
//set form field values.
parent.viewModel.form.fill(todo);
//update tenants dropdown for selected listing.
parent.tenantFilter.getByListing();
//show popup.
$("#popup").modal("show");
};
self.markComplete = function (todo) {
parent.markComplete(todo);
};
self.remove = function (todo) {
var result = confirm("Are you sure that you want to delete this To-Do?");
if (result) {
//save changes.
utils.ajax(basePath + "properties/deletetodo",
{ id: todo.Id },
function (success) {
//refresh results.
self.todos.remove(todo);
//show result.
utils.showSuccess('The To-Do has been deleted successfully');
}
);
}
};
self.toggleShowCompleted = function () {
parent.showCompleted(!parent.showCompleted());
$("#showCompletedTodos").text(parent.showCompleted() ? "Show Active" : "Show Completed");
};
self.update = function (todo) {
var existingToDo = _.find(self.todos(), function (item) { return item.Id() == todo.Id(); });
existingToDo = todo;
};
//load todos from server.
utils.ajax(basePath + "properties/gettodos",
{ id: $("#originalListingId").val(), showCompleted: parent.showCompleted() },
function (results) {
var mappedTodos = $.map(results, function (item) { return new schemas.ToDo(item, parent); });
self.todos(mappedTodos);
$("#grid-content").unblock();
}
);
}
function ToDoFormViewModel() {
//init.
var self = this;
self.todo = ko.observable({});
utils.setupPopupForm(self.saved);
//operations.
self.fill = function (todo, isEdit) {
//set form field values.
self.todo = todo;
if (todo.Id()) {
//update tenants dropdown for selected listing.
parent.tenantFilter.getByListing();
}
//show popup.
$("#popup").modal("show");
};
self.save = function (todo) {
self.todo = todo;
$("#form").submit();
};
self.saved = function (result) {
var todo = new schemas.ToDo(result.todo, parent);
if (result.isInsert)
parent.viewModel.list.todos().push(todo);
else
parent.viewModel.list.update(todo);
utils.showSuccess("Your To-Do has been saved successfully.");
};
self.markComplete = function (todo) {
parent.markComplete(todo);
};
}
this.markComplete = function (todo) {
var result = confirm("Are you sure that you want to mark this To-Do complete?");
if (result) {
//save changes.
utils.ajax(basePath + "properties/marktodocomplete", {
id: todo.Id()
},
function () {
todo.IsComplete(true);
//show success.
utils.showSuccess('Your To-Do has been marked completed');
} .bind(this)
);
}
}
this.init();
}
One possible solution is to replace:
data-bind="click: $parent.edit"
with
data-bind="click:$root.viewModel.list.edit"