Detail page does not bind with knockout - jquery-mobile

There are four screens in my sample application, Login,Dash Board, List Page and Details Page,Here login page, Dash Board , List Page bindings are working, but Details page details not populate as I expected, working example http://jsfiddle.net/uderox/gY9Nt/3/
Html
<div data-role="page" data-theme="a" id="loginPage" data-bind="with:loginModel">
<div data-role="content">
<p>
<input type="text" class="input" placeholder="username" data-bind="value: userName"/>
<input type="password" class="input" placeholder="Password" data-bind="value: password"/>
</p>
<p>
<button data-bind='click: submit'>Login</button>
</p>
</div>
</div>
<div data-role="page" data-theme="a" id="dashBoardPage" data-bind="with:dashboardViewModel">
<div data-role="content">
<label>User Id<span data-bind="text:uId"></span></label>
<input type="button" value="Click" data-bind="click:goToList"/>
</div>
</div>
<div data-role="page" id="listViewPage" data-bind="with:listViewModel">
<div>
<div id="listViewDiv">
<ul data-role="listview" data-bind="foreach: hospitalList">
<li data-bind="click: $parent.selectHospital">
<h2>Hospital Id:<span data-bind="text:id"></span></h2>
<p>Name <span data-bind="text:name"></span></p>
</li>
</ul>
</div>
</div>
</div>
<div data-role="page" id="detailsView">
Back
Home
<div>
<h2>Hospital Id : <span data-bind="text:id"></span></h2>
<input data-mini="true" tabindex="5" data-bind="value: name"
id="name"/>
</div>
</div>
Js
var LoginViewModel = function (parantModel) {
var self = this;
self.userName = ko.observable();
self.password = ko.observable();
self.submit = function () {
parantModel.dashboardViewModel.uId(self.userName());
navigationService.navigateTo($('#dashBoardPage'));
}
}
var DashboardViewModel = function(parentModel){
var self = this;
self.uId = ko.observable();
self.goToList = function(){
navigationService.navigateTo($('#listViewPage'));
}
}
var ListViewModel = function(parentViewModel){
var self = this;
self.selectedHospital = ko.observable();
var objList = [{"id":"001","name":"Hospital1","location":"SL"},{"id":"002","name":"Hospital2","location":"SL"}].map(function(hospital){return new HospitalViewModel(hospital);});
self.hospitalList = objList;
self.selectHospital = function(hospital){
parentViewModel.detailViewModel(hospital);
alert("000");
navigationService.navigateTo($('#detailsView'));
};
}
var HospitalViewModel = function(data){
var self = this;
self.id = data.id;
self.name = ko.observable(data.name);
}
function PageViewModel (){
var self = this;
self.loginModel = new LoginViewModel(self);
self.dashboardViewModel = new DashboardViewModel(self);
self.listViewModel = new ListViewModel(self);
self.detailViewModel = ko.observable();
}
function NavigationService(){
var self = this;
self.navigateTo = function(pageId){
$.mobile.changePage(pageId);
};
}
var navigationService = new NavigationService();
ko.applyBindings(new PageViewModel());
Why it does not populate data to Details page,I am binding it using ko.obsevable(),

You haven't bound your detailViewModel.
change
<div data-role="page" id="detailsView">
to
<div data-role="page" id="detailsView" data-bind="with:detailViewModel">

Related

How to perform a login identification process in the best way?

I have 2 inputs boxes: Public key (user name) and Private key (password). Also I have a hidden warning label.
This is my code (and it's perfectly working ):
<script language="javascript">
function SendLoginData() {
document.getElementById("LoginErrorLabel").style.display = "none";
var url = "/DappAccount/CheckAccount";
$.post(url, { PublicKey: $("#public_key_input").val(), PrivateKey: $("#private_key_input").val() }, function (data) {
if (data == false) {
document.getElementById("LoginErrorLabel").style.display = "block";
return;
}
else {
document.getElementById("loader").style.display = "block";
$("#myform").submit()
}
});
}
</script>
<div class="container">
#using (Html.BeginForm("AccountMainPage", "DappAccount", FormMethod.Post, new { #id = "myform" }))
{
<div class="row justify-content-center">
#Html.TextBoxFor(m => m.publicKey, new { id = "public_key_input", placeholder = "Ethereum Public Key", required = "required" })
</div> <br />
<div class="row justify-content-center">
#Html.TextBoxFor(m => m.privateKey, new { id = "private_key_input", placeholder = "Ethereum Private Key", required = "required", type = "password" })
</div> <br />
<div class="row justify-content-center">
<img id="loader" style="display: none;" src="https://s5.gifyu.com/images/Loader5a73d3b26568dbc4.gif" alt="Loader5a73d3b26568dbc4.gif" border="0" />
</div> <br />
}
<div class="row justify-content-center">
<input id="submit" type="button" value="Login" class="btn btn-primary" onclick="SendLoginData()" />
</div>
<label id="LoginErrorLabel" style="color: red; display: none;">*Wrong login detail !</label>
</div>
What I'm doing here is:
1) Send username&password to the 'CheckAccount' method in the controller, the method returns true/false.
2) If false, show label,
if true, show gif image and send again the details to ActionResult (=AccountMainPage) which returns a new view.
I just wonder, is there a better/shorter way to do it using one post or one method? I heard something about the partial views in MVC, no idea what to do with it. People told me that what I did here is too old for MVC

AngularJs , MVC During the Edit mode why Values not Binding in DropdownList

Im using Mvc with Angularjs here I am fetching data from Database using join and Display data in table when i click on Edit button that particular row is binding in Bootstrap "modal" but why country,State Names not binding in the dropdown.
Here i'm showing Linq query:
public JsonResult GetAssData()
{
var x = (from n in db.Accessors
join ctr in db.Countrys on n.CountryID equals ctr.CountryID
join sts in db.States on n.StateID equals sts.StateID
select new { n.Id, n.Name, n.Email, n.Password, n.GEnder, n.Active, ctr.CountryName, sts.StateName, });
return new JsonResult { Data = x, JsonRequestBehavior = JsonRequestBehavior.AllowGet };
}
public JsonResult EditSer(int id = 0)
{
var x = (from n in db.Accessors
where n.Id == id
join ctr in db.Countrys on n.CountryID equals ctr.CountryID
join sts in db.States on n.StateID equals sts.StateID
select new
{
n.Id,
n.Name,
n.Email,
n.Password,
n.GEnder,
ctr.CountryName,
sts.StateName,
});
return new JsonResult { Data = x, JsonRequestBehavior = JsonRequestBehavior.AllowGet };
}
public JsonResult BindCtry()
{
var x = from n in db.Countrys select n;
return new JsonResult { Data = x, JsonRequestBehavior = JsonRequestBehavior.AllowGet };
}
public JsonResult BindStates(int Id = 0)
{
var x = from n in db.States
where n.CountryID == Id
select n;
return new JsonResult { Data = x, JsonRequestBehavior = JsonRequestBehavior.AllowGet };
}
AngularJs
app.controller('MyBindCNtrls', function ($scope, MyBindServiceservice) {
GetAssusData();
function GetAssusData() {
var xxx = MyBindServiceservice.getAss();
xxx.then(function (d) {
$scope.access = d.data;
})
}
$scope.EditEmp = function (Emp) {
alert('in EditModes')
var sss = MyBindServiceservice.EditAssFun(Emp.Id);
sss.then(function (d) {
$scope.Id = Emp.Id;
$scope.Name = Emp.Name;
$scope.GEnder = Emp.GEnder;
$scope.Email = Emp.Email;
$scope.Password = Emp.Password;
$scope.CountryID = Emp.CountryID;
$scope.CountryName = Emp.CountryName;
$scope.StateName = Emp.StateName;
$scope.ValidAction = 'Update';
$('#Modalpopup').modal('show');
})
}
})
app.service('MyBindServiceservice', function ($http) {
this.getAss = function () {
var xx = $http({
url: '/Bindctrl/GetAssData',
method: 'Get',
params: JSON.stringify(),
content: { 'content-type': 'application/Json' }
})
return xx;
}
this.EditAssFun = function (Id) {
alert('enter in edit ser')
var sts = $http({
url: '/Bindctrl/EditSer',
method: 'Get',
params: {
Id: JSON.stringify(Id)
}
});
return sts;
}
});
<div ng-controller="MyBindCNtrls">
<table class="table table-bordered">
<tr>
<th><b>Id</b></th>
<th><b>Name</b></th>
<th><b>Email</b></th>
<th><b>Password</b></th>
<th><b>Gender</b></th>
<th><b>CountryName</b></th>
<th><b>StateName</b></th>
<th><b>Action</b></th>
</tr>
<tr ng-repeat="Accessor in access">
<td>{{Accessor.Id}}</td>
<td>{{Accessor.Name}}</td>
<td>{{Accessor.Email}}</td>
<td>{{Accessor.Password}}</td>
<td>{{Accessor.GEnder}}</td>
<td>{{Accessor.CountryName}}</td>
<td>{{Accessor.StateName}}</td>
<td>
<button type="button" class="btn btn-success btn-sm" value="Edit" ng-click="EditEmp(Accessor)"><span class="glyphicon glyphicon-pencil"></span></button>
</td>
</tr>
</table>
<div class="modal" id="Modalpopup">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button class="close" data-dismiss="modal">×</button>
<h3>{{msg}}Login Details</h3>
</div>
<div class="modal-body">
<form novalidate name="f1" ng-submit="SaveDb(Ass)">
<div>
{{Errormsg}}
</div>
<div class="form-horizontal">
<div class="form-group">
<div class="row">
<div class="col-sm-2" style="margin-left:20px">
Name
</div>
<div class="col-sm-8">
<input type="text" class="form-control" name="nam" ng-model="Name" ng-class="Submittes?'ng-dirty':''" required autofocus />
<span class="Error" ng-show="(f1.nam.$dirty || Submittes) && f1.nam.$error.required">Enter Name</span>
</div>
</div>
</div>
<div class="form-group">
<div class="row">
<div class="col-sm-2" style="margin-left:20px">
Email
</div>
<div class="col-sm-8">
<input type="text" class="form-control" name="MailId" ng-model="Email" ng-class="Submittes?'ng-dirty':''" required />
<span class="Error" ng-show="(f1.MailId.$dirty || Submittes) && f1.MailId.$error.required">Enter Email</span>
</div>
</div>
</div>
<div class="form-group">
<div class="row">
<div class="col-sm-2" style="margin-left:20px">
Password
</div>
<div class="col-sm-8">
<input type="text" name="psw" class="form-control" ng-model="Password" ng-class="Submittes?'ng-dirty':''" required />
<span class="Error" ng-show="(f1.psw.$dirty || Submittes) && f1.psw.$error.required">Enter Password</span>
</div>
</div>
</div>
<div class="form-group">
<div class="row">
<div class="col-sm-2" style="margin-left:20px">
Gender
</div>
<div class="col-sm-8">
<input type="radio" value="Male" name="Gen" ng-model="GEnder" ng-class="Submittes?'ng-dirty':''" required />Male
<input type="radio" value="Fe-Male" name="Gen" ng-model="GEnder" ng-class="Submittes?'ng-dirty':''" required />Fe-Male
<br />
<span class="Error" ng-show="(f1.Gen.$dirty || Submittes) && f1.Gen.$error.required">Select Gender</span>
</div>
</div>
</div>
<div class="form-group">
<div class="row">
<div class="col-sm-2" style="margin-left:20px">
Country
</div>
<div class="col-sm-8">
<select class="form-control" name="cntrsy" ng-options="I.CountryID as I.CountryName for I in CountryList" ng-model="CountryID" ng-change="GetStates()" ng-class="Submittes?'ng-dirty':''" required>
<option value="">Select Country</option>
</select>
<span class="Error" ng-show="(f1.cntrsy.$dirty || Submittes) && f1.cntrsy.$error.required">Select Country</span>
{{CountryName}}
</div>
</div>
</div>
<div class="form-group">
<div class="row">
<div class="col-sm-2" style="margin-left:20px">
StateName
</div>
<div class="col-sm-8">
<select class="form-control" name="sts" ng-options="I.StateID as I.StateName for I in StateList" ng-model="StateID" ng-change="GetCitys()" ng-class="Submittes?'ng-dirty':''" required>
<option value="">Select Country</option>
</select>
<span class="Error" ng-show="(f1.sts.$dirty || Submittes) && f1.sts.$error.required">Select States</span>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<input type="submit" class="btn btn-sm btn-success pull-right" value="{{ValidAction}}" ng-class="SaveAndSubmit()" />
#* <input type="button" class="btn btn-sm pull-right" value="Cancel" id="BtnCancel" />*#
</div>
</form>
</div>
</div>
</div>
</div>
</div>

How to populate different bootstrap dropdowns using Knockout and jquery

I'm trying to get data from database and populate different bootstrap dropdowns.
The table contains the following fields: id, ipAddress, hostName, recordNumber
The Model:
function myModel(){
var self = this;
self.id = ko.observable();
self.ipAddress = ko.observable();
self.hostName = ko.observable();
self.recordNumber = ko.observable();
}
The ViewModel
function myViewModel(){
var self = this;
self.ipAddresses = ko.observableArray();
self.hostNames = ko.observableArray();
self.recordNumbers = ko.observableArray();
self.selectedIpAddress = ko.observable("");
self.selectIpAddress = function (){
self.selectedIpAddress ();
}
}
var uri = 'api/items';
var array = [];
$.getJSON(uri)
.done(function (data) {
$.each(data, function (index, item) {
array.push(item);
self.ipAddresses(array.ipAddress);
self.hostNames(array.hostName);
self.recordNumbers(array.recordNumber);
});
});
The array contains well the data but I don't know how to access the different fields of the table, I tried this but it doesn't work:
self.ipAddresses(array.ipAddress);
self.hostNames(array.hostName);
self.recordNumbers(array.recordNumber);
Html code of one dropdown:
<div class="input-group">
<input type="text" class="form-control"data-bind="value:selectedIpAddress"
<div class="input-group-btn">
<button type="button" id="dropDownIpAddress" class="btn btn-default dropdown-toggle" data-toggle="dropdown">
<span class="caret"></span>
</button>
<ul class="dropdown-menu dropdown-menu-right" role="menu" data-bind="foreach: ipAddresses">
<li><a role="menuitem" href="#" data-bind="text: ipAddress, click: myViewModel.selectIpAddress"></a></li>
</ul>
</div>
</div>
JSFiddle

How to update input element using selected value from bootstrap dropdown

I would like to use knockout for updating dynamically the input element by the selected value from the dropdown but I don't understand how to use the code I commented here bellow with the dropdown and I'm not sure if it's the right way to do... Please help me understand and fix this problem.
View:
<div class="form-group">
<label for="dropDownRelationType">Business relation type</label>
<div class="input-group">
<input type="text" class="form-control" id="txtRelationTypeId" name="txtRelationTypeId" data-bind="value: companyModel.relationTypeId" placeholder="Business relation type"
<div class="input-group-btn">
<button type="button" id="dropDownRelationType" class="btn btn-default dropdown-toggle" data-toggle="dropdown" aria-haspopup="true">
<span class="caret"></span>
</button>
<ul class="dropdown-menu" role="menu" data-bind="foreach: relationTypes">
<li><a role="menuitem" href="#" data-bind="text: relationTypeId"></a></li>
</ul>
</div>
</div>
</div>
Knockout:
function companyModel() {
var self = this;
self.companyName = ko.observable("");
self.status = ko.observable("1");
self.relationTypeId = ko.observable("");
self.relationTypes = ko.observableArray();
}
function CompanyViewModel() {
var self = this;
self.companyModel = new companyModel();
self.relationTypes = ko.observableArray([
{ relationTypeId: "1" }, { relationTypeId: "2" }, { relationTypeId: "3" }, { relationTypeId: "4" }
])
//-------------------------------------------------------
//self.relationTypes.subscribe(function (selectedRelationTypeId) {
// shouter.notifySubscribers(selectedRelationTypeId, "valueToPublish");
//});
//shouter.subscribe(function (selectedRelationTypeId) {
// self.relationTypeId(selectedRelationTypeId);
//}, self, "valueToPublish");
//-------------------------------------------------------
}
var companyViewModel = new CompanyViewModel();
$(function () {
ko.applyBindings(companyViewModel);
});
You can add an observable to select the relationTypeId like
function CompanyViewModel() {
var self = this;
self.companyModel = new companyModel();
self.selectedRelationTypeId = ko.observable();
self.relationTypes = ko.observableArray([
{ relationTypeId: "1" }, { relationTypeId: "2" }, { relationTypeId: "3" }, { relationTypeId: "4" }
])
self.selectRelationTypeId = function(relationType){
self.selectedRelationTypeId(relationType.relationTypeId);
};
}
and change your html markup as
<div class="form-group">
<label for="dropDownRelationType">Business relation type</label>
<div class="input-group">
<input type="text" class="form-control" id="txtRelationTypeId" name="txtRelationTypeId" data-bind="value: selectedRelationTypeId" placeholder="Business relation type" />
<div class="input-group-btn">
<button type="button" id="dropDownRelationType" class="btn btn-default dropdown-toggle" data-toggle="dropdown" aria-haspopup="true">
<span class="caret"></span>
</button>
<ul class="dropdown-menu" role="menu" data-bind="foreach: relationTypes">
<li><a role="menuitem" href="#" data-bind="text: relationTypeId, click: $root.selectRelationTypeId"></a></li>
</ul>
</div>
</div>
</div>
You should be able to see the selection you make in the input field.

Page flickers when Angular JS is used in Bootstrap modal, but works fine after reload. (tried ngCloak too)

Application Description:
I am making a simple Ecommerce website(single page product listing) using AngularJS and Rails. It only handles Cash On Delivery Orders. The user adds products and checksout. All this process is done in Angular. The cart is stored in localstorage.When he checksout a modal pops up asking him to choose choose between two shipping methods. Depending on the shipping method he chooses the price which is displayed on the bootstrap modal has to be updated.
Problem Description:
The page flickers(the curly braces appear) when I try to do this. When I reload the whole thing it works properly.
After some research I found that I have to use $compile but I am not sure of how to use it. i read several tutorials but I am not able to figure it out.
Here is my angular code. The two functions I used in bootstrap modal are shippingCharges(), totalPrice(). They are at the end of the angular code.
<script>
var products = angular.module('products', []);
products.controller('ListController', ['$scope', function($scope) {
$scope.categories = JSON.parse('<%= j raw(#categories_hash.to_json) %>');
$scope.activeCategory = null;
$scope.cart = JSON.parse(localStorage.getItem('cart'));
if (!!$scope.cart) {
angular.forEach($scope.cart, function(item_quantity, item_id) {
$scope.categories.forEach(function(category, index1) {
category.products.forEach(function(product, index2) {
if (item_id == product.id) {
product.ordered_quantity = item_quantity;
}
});
});
});
};
$scope.formData = {
shipping: "scheduled"
};
$scope.addProductToCart = function(product_id) {
// event.preventDefault();
var cart = $scope.cart;
if (!cart) {
cart = {}
}
if (!cart[product_id]) {
cart[product_id] = 0;
}
cart[product_id] += 1;
localStorage.setItem('cart', JSON.stringify(cart));
$scope.cart = cart;
};
$scope.increaseQuantity = function(product) {
product.ordered_quantity += 1;
$scope.addProductToCart(product.id);
};
$scope.decreaseQuantity = function(product) {
product.ordered_quantity = product.ordered_quantity - 1;
var cart = $scope.cart;
if (!cart) {
cart = {}
}
cart[product.id] -= 1;
localStorage.setItem('cart', JSON.stringify(cart));
$scope.cart = cart;
};
$scope.removeProductFromCart = function(product_id) {
var cart = $scope.cart;
cart[product_id] = 0;
localStorage.setItem('cart', JSON.stringify(cart));
$scope.cart = cart;
}
$scope.totalPrice = function() {
total = 0;
$scope.categories.forEach(function(category, index) {
category.products.forEach(function(product, index1) {
total += product.price*product.ordered_quantity;
});
});
return total;
};
$scope.toggleCategory = function(category) {
if ($scope.activeCategory == category.category_id) {
$scope.activeCategory = null;
} else {
$scope.activeCategory = category.category_id;
}
};
$scope.shouldShowCategory = function(category) {
return($scope.activeCategory == category.category_id);
};
$scope.shippingCharges = function() {
var cart = $scope.cart;
var shippingcost;
if ($scope.formData.shipping == "scheduled"){
shippingcost = 35;
}else if ($scope.formData.shipping == "unscheduled"){
shippingcost = 75;
}
cart["shipping"]=shippingcost;
localStorage.setItem('cart', JSON.stringify(cart));
return shippingcost;
}
}]);
</script>
Boostrap Modal Code
<div class="modal fade" id="checkoutModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true" ng-controller="ListController" ng-cloak >
<div class="modal-dialog modal-lg">
<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>
<h4 class="modal-title" id="myModalLabel">Information for delivery</h4>
</div>
<div class="modal-body checkout-details">
<form id="checkoutForm" class="form-horizontal">
<div id="checkoutLoading" class="progress progress-striped active hidden">
<div class="progress-bar progress-bar-success" style="width: 100%"></div>
</div>
<fieldset>
<legend>Choose a delivery method</legend>
<p>We are making a schedule delivery to <strong><%= delivery_timing[0] %></strong> on <strong><%= delivery_timing[1] %></strong>. If you are not located in the mentioned places please choose an unscheduled delivery</p>
<div class="radio">
<label><input type="radio" name="shipping" value="scheduled" ng-model="formData.shipping" ng-change="setShipping('scheduled')">Scheduled Delivery(Rs. 35)</label>
</div>
<div class="radio">
<label><input type="radio" name="shipping" value="unscheduled" ng-model="formData.shipping" ng-change="setShipping('unscheduled')">Unscheduled Delivery(Rs.75)</label>
</div>
<p class="ng-cloak">Total: {{shippingCharges() + totalPrice()}}</p>
</fieldset>
<fieldset>
<legend>Please provide delivery details:</legend>
<div class="errorMessage alert alert-dismissible alert-danger hidden">
<strong>Oh snap!</strong> Please provide phone number and address.
</div>
<div id="checkoutEmailFormGroup" class="form-group">
<label for="checkoutPhone">Email</label>
<input type="email" class="form-control" id="checkoutEmail" placeholder="me#example.com" >
</div>
<div id="checkoutPhoneFormGroup" class="form-group">
<label for="checkoutPhone">Phone</label>
<input type="phone" class="form-control" id="checkoutPhone" placeholder="+91-9999-999-999" >
</div>
<div id="checkoutAddressFormGroup" class="form-group">
<label for="checkoutAddress">Address</label>
<textarea class="form-control" id="checkoutAddress" placeholder="Plot No
Street Name
City" rows="5"></textarea>
</div>
</fieldset>
</form>
</div>
<div class="modal-footer">
<p class="ng-cloak" >Total cost: {{shippingCharges() + totalPrice()}}</p>
<button type="button" class="btn btn-default" data-dismiss="modal">Go Back</button>
<button id="checkout_trigger" type="button" class="btn btn-brown">Confirm</button>
</div>
</div>
</div>
</div>
Can you please let me know how to compile the code in the Bootstrap modal?

Resources