I want to disable button Assign when it clicked, bacause it should assign only once so i can achieve this, I have done the following code in HTML:
<table class="table details">
<thead>
<tr>
<th sort-by="firstName">User Name</th>
<th sort-by="lastName">Description</th>
<th sort-by="Budget" sort-init="desc">Bid Amount</th>
<th sort-by="lastName">Action</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="issue in issues | filter:filter">
<td><strong><a href="/ViewBid/Index?{{ issue.User_ID }}" />{{ issue.UserName }} </strong></td>
<td><a href="/ViewBid/Index?{{ issue.User_ID }}" />{{ issue.Description }}</td>
<td><a href="/ViewBid/Index?{{ issue.User_ID }}" />{{issue.Bid_amt}}</td>
<td>
<div ng-controller="ExampleCtrl_Assign">
<div ng-show="AsgHide">
<button type="button" ng-click="AssignRecord(issue.ID,issue.Description,issue.Bid_amt)">Assign</button>
</div>
</div>
<div ng-controller="ExampleCtrl_Delete">
<div ng-show="AsgHide" >
<button type="button" ng-click="DeleteRecord(issue.ID)">Delete</button>
</div>
</div>
</td>
</tr>
</tbody>
</table>
And JavaScript Code is as following:
var app = angular.module('siTableExampleApp_Assign', []);
app.controller('ExampleCtrl_Assign', ['$scope','$http', function ($scope, $http) {
var user2 = window.localStorage.getItem('UserId');
var Basic = window.localStorage.getItem('Basic');
var Token = window.localStorage.getItem('Token');
$scope.FunctionDisable = function (i) {
$("#rbutton'+i+'").attr("disabled", "disabled");
}
$scope.AssignRecord = function (ID, Description, Bid_amt) {
var BidID = ID;
var date = new Date();
encodedString = {
"ID": 1,
"Travel_Info_ID": travel_info_id,
"Bid_ID": parseInt(BidID),
"Description": Description,
"Bid_amt": Bid_amt,
"Status": "InProcess",
"User_ID": user2,
"Entry_Date": date,
"Update_Date": date
}
$http({
method: 'POST',
url: 'http://saisoftwaresolutions.com/v1/Assigned_Bids/Assigned_Bid/Create',
data: encodedString,
headers: {
'Authorization': 'Basic ' + Basic,
'Token': Token
}
})
.success(function (data, status, headers, config) {
console.log(headers());
console.log(data);
if (status === 200) {
//window.location.href = 'http://localhost:22135/BDetail/Index';
} else {
$scope.errorMsg = "Login not correct";
}
})
.error(function (data, status, headers, config) {
$scope.errorMsg = 'Unable to submit form';
})
Use can always use ng-disabled directive provided by Angular to disabled html elements.
I have made one example based on your requirements and help it will solve your issue:
<div ng-app ng-controller="MyCtrl">
<ul>
<li ng-repeat="item in items">{{item.User_ID}}: {{item.User_Name}}
<button ng-click="handleClick($index)" ng-disabled="item.disabled">
{{item.User_Name}}
</button>
</li>
</ul>
</div>
function MyCtrl($scope) {
$scope.items = [
{
User_ID: '10',
disaled: false,
User_Name: 'ABC'
}, {
User_ID: '11',
disaled: false,
User_Name: 'XYZ'
}
];;
$scope.handleClick = function(index){
$scope.items[index].disabled = true;
}
}
Angular has a directive just for this: ng-disabled.
From their official documentation:
This directive sets the disabled attribute on the element if the
expression inside ngDisabled evaluates to truthy.
So you can set a boolean value in your code-behind to true and have that evaluate inside your button. For example:
<button type="button" ng-disabled="issue.IsDisabled" ng-click="AssignRecord(issue.ID,issue.Description,issue.Bid_amt)">Assign</button>
Also, check out the example in their documentation and this jsfiddle: https://jsfiddle.net/simpulton/q8r4e/.
Related
I can get the elements sent from the backend.But the text can't display.I don't know why.
here is my html :
<!-- <form action=""> -->
<div class=" form-group">
<input v-model="wd" #keyup="keyup($event)" type="text" class="form-control" />
<!-- <ul class="list-group"> -->
<table>
<tr>
<th v-for="item in title"><div style="width:500px">{{item}}</div> </th>
</tr>
<tr v-for="item in arr" :key='item'>
<td>{{item.name}}</td>
<td>{{item.sort}}</td>
<td>{{item.company}}</td>
</tr>
</table>
</div>
here is My Vue:
el: "#app",
data: {
wd: '',
arr: [],
listIndex: -1,
title:['name','sort','company'],
},
methods: {
keyup(event) {
var url = "/search/search/"
axios.get(url, {
params: {
q: this.wd,
}
}).then(res => {
console.log(res);
this.arr = res.data.list;
})
}
}
})
;
I know the data was got.Because the number of the items in loop is exactly correct.When I console.log(res.data.list),I can view the data from the backend.But they can't display in my page.
I will be very appreciate it if you could help me.Thank you!
enter image description here
I think the problem is in your reference to this.arr in your callback. When the AJAX call returns, this is scoped to the response, not your Vue object.
You can overcome this by inserting a variable prior to the AJAX call, like this:
var vm = this;
axios.get(url, {
then, in the callback, instead of this.arr = res.data.list;, do this:
vm.arr = res.data.list;
The field data must be reactive
data() {
return{
wd: '',
arr: [],
listIndex: -1,
title:['name','sort','company'],
}
}
i have a big problem.
I have file transferCtrl.js and i want create function which will show only persons to which the bank transfer was made before.
I tries to pass data to a new table, but i can’t to this.
And this data history transfer i want to show in datalist. Please help me, i’m newbie.
This is my transferCtrl.js
app.controller(‘TransfersCtrl’, [ ‘$http’, ‘common’, function($http, common) {
console.log(‘Controller TransfersCtrl start’)
var ctrl = this
This is my transferCtrl.js
app.controller('TransfersCtrl', [ '$http', 'common', function($http, common) {
console.log('Controller TransfersCtrl start')
var ctrl = this
ctrl.formatDateTime = common.formatDateTime
ctrl.history = []
ctrl.recipients = []
ctrl.recipient = null
ctrl.transfer = {
delta: 1.00
}
ctrl.amount = 0
var refreshHistory = function() {
$http.get('/transfer').then(
function(res) {
ctrl.history = res.data
$http.delete('/transfer').then(
function(res) { ctrl.amount = res.data.amount },
function(err) {}
)
},
function(err) {}
)
}
refreshHistory()
ctrl.doTransfer = function() {
$http.post('/transfer?recipient=' + ctrl.recipient._id, ctrl.transfer).then(
function(res) {
refreshHistory()
},
function(err) {}
)
}
$http.get('/personList').then(
function(res) {
ctrl.recipients = res.data
ctrl.recipient = ctrl.recipients[0]
},
function(err) {
ctrl.recipients = []
ctrl.recipient = null
}
)
}])
This is my transferView.html
<table class="table table-stripped">
<tr">
<th>date</th>
<th>sender</th>
<th>recipient</th>
<th>amount before/th>
<th>transfer</th>
<th>amount after</th>
</tr>
<tr ng-repeat="transfer in ctrl.history">
<td ng-bind="ctrl.formatDateTime(transfer.date)"></td>
<td ng-bind="transfer.senderFirstName+' '+transfer.senderLastName"></td>
<td ng-bind="transfer.recipientFirstName+' '+transfer.recipientLastName"></td>
<td ng-bind="transfer.amount_after - transfer.delta"></td>
<td ng-bind="transfer.delta"></td>
<td ng-bind="transfer.amount_after"></td>
</tr>
</table>
<br/><br/>
<div class="panel panel-default">
<div class="panel-heading">transfer</div>
<div class="panel-body">
<form class="form form-inline">
<select class="form-control" ng-model="ctrl.recipient" ng-options="option.firstName+' '+option.lastName for option in ctrl.recipients track by option._id">
</select>
<input class="form-control" type="number" ng-model="ctrl.transfer.delta"/>
<button class="btn btn-default" ng-click="ctrl.doTransfer()" ng-disabled="ctrl.transfer.delta > ctrl.amount">transfer</button>
</form>
</div>
</div>
It probably goes without saying that I'm quite new to angular as I'm trying to accomplish a relatively simple task, and I've come here for some help
I'm recreating our company's password vault using angular.
Here is what I am trying to accomplish.
The page loads with a list of accounts. Most the information is visible except for the password. I have a button that when clicked, hides the button, queries the database, logs who queried password, and displays the password to the user. The passwords are clear text because they aren't passwords for client accounts or anything sensitive, it exists for our employees to reference how/where to login to various websites we use for day to day business.
My HTML looks as follows:
<tr ng-repeat="account in resp.PasswordVaultAccounts">
<td>{{account.Name}}</td>
<td>{{account.Username}}</td>
<td><button ng-click="showPassword(account.AccountId);" class="btn btn-primary">View</button><span></span></td>
<td>{{account.Comments}}</td>
</tr>
My scope controller looks as follows
$scope.showPassword = function (accountId) {
passwordVaultData.getAccountPassword(accountId)
.$promise
.then(function (r) {
//success
}, function (r) {
//fail
});
}
My showPassword() method works and returns the correct password, but I can't figure out how to hide the button and display the password.
Using the ng-show and ng-hide directives against the password on the account object should suffice for modifying the UI
<tr ng-repeat="account in resp.PasswordVaultAccounts">
<td>{{account.Name}}</td>
<td>{{account.Username}}</td>
<td>
<button ng-hide="account.Password" ng-click="showPassword(account.AccountId);" class="btn btn-primary">View</button>
<span ng-show="account.Password">{{account.Password}}</span>
</td>
<td>{{account.Comments}}</td>
</tr>
As for the promise resolution, you want the getAccountPassword to return a promise, I will make an assumption about it's content below
function getAccountPassword(account) {
var deferred = $q.defer();
$http.get('api/vault/' + account.AccountId).then(function(r) {
deferred.resolve(r);
}, function(r) {
deferred.reject(r);
});
return deferred.promise;
}
$scope.showPassword = function (account) {
getAccountPassword(account.AccountId).then(function(password) {
account.Password = password;
}, function(password) {
account.Password = undefined; // some type of error handling here
});
}
Because the promise is executed in the context of an $http call, the digest cycle will run and the elements will be shown based on whether password is populated.
You can accomplish it by either ng-if or ng-show/hide:
Quick sample below:
<tr ng-repeat="account in resp.PasswordVaultAccounts">
<td>{{account.Name}}</td>
<td>{{account.Username}}</td>
<td>
<button ng-if="!account.password" ng-click="showPassword(account);" class="btn btn-primary">View</button><span></span></td>
<span ng-if="account.password">{{password}}</span>
<td>{{account.Comments}}</td>
</tr>
$scope.showPassword = function (account) {
account.password = passwordVaultData.getAccountPassword(account.AccountId)
.$promise
.then(function (r) {
//success
}, function (r) {
//fail
});
}
Please see demo below
var app = angular.module('app', []);
angular.module('app').
controller('firstCtrl', function($scope) {
$scope.resp = {
PasswordVaultAccounts: [{
AccountId: 1,
URL: "bbc.co.uk",
Username: "Jack",
Comments: "White"
}, {
AccountId: 2,
URL: "bbc.co.uk",
Username: "Mike",
Comments: "Green"
}, {
AccountId: 3,
URL: "bbc.co.uk",
Username: "Tim",
Comments: "Red"
}
]
}
$scope.showPassword = function(account) {
//call you backend and on sucess add that :
// passwordVaultData.getAccountPassword(account.accountId)
// .$promise
// .then(function (r) {
account.showpass = true;
account.pass = account.Username + " password is *****"
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body ng-app="app">
<div ng-controller="firstCtrl">
<table>
<tr ng-repeat="account in resp.PasswordVaultAccounts">
<td>{{account.Name}}
</td>
<td>{{account.Username}}</td>
<td>
<button ng-click="showPassword(account);" class="btn btn-primary" ng-hide="account.showpass">View</button>
<span ng-show="account.showpass">{{account.pass}}</span>
</td>
<td>{{account.Comments}}</td>
</tr>
</table>
</div>
</body>
How to update the knockout js observablearray in UI part..Initially Im editing a item and in update function i'm trying to update a particular item so im sending the current item object to service and getting the updated vales as response. Inside the response I need to update the observablearray as well the UI too.. I have tried some thing like this and its not working for me... please check in http://jsfiddle.net/up8rB/20/
<div data-bind="ifnot: Role()">
<label for="description">Description</label>
<input type="text" data-bind="value: Description" class="form-control" placeholder="Enter the description..." />
<button data-bind="click: $root.create"> Create</button>
</div>
<div data-bind="if: Role">
<label for="description">Description</label>
<input type="text" data-bind="value: Role().Description" class="form-control" placeholder="Enter the description..." />
<button data-bind="click: $root.update"> Save</button>
</div>
<table id="example1" class="table table-bordered table-striped" data-bind="visible: Roles().length > 0">
<thead>
<tr>
<th>RoleID</th>
<th>Description</th>
<th>Actions</th>
</tr>
</thead>
<tbody data-bind="foreach: Roles">
<tr>
<td data-bind="text: $data.RoleID"></td>
<td data-bind="text: $data.Description"></td>
<td>
<button data-bind="click: $root.edit" >Edit</button>
<button data-bind="click: $root.delete" >Delete</button>
</td>
</tr>
</tbody>
</table>
function RoleViewModel() {
var self = this;
self.RoleID = ko.observable("0");
self.Description = ko.observable().extend({
required: { message: 'Please supply description ..' }
});
var Role = {
RoleID: self.RoleID,
Description: self.Description
};
self.Role = ko.observable();
self.Roles = ko.observableArray();
$.ajax({
url: 'Service.svc/RoleCollection',
cache: false,
type: 'GET',
contentType: 'application/json; charset=utf-8',
data: {},
success: function (data) {
self.Roles(data); //Put the response in ObservableArray
}
});
self.edit = function (Role) {
self.Role(Role);
}
self.update = function () {
var Role = self.Role();
$.ajax({
url: '..service.svc/UpdateRole',
cache: false,
type: 'PUT',
contentType: 'application/json; charset=utf-8',
data: ko.toJSON(Role),
success: function (data) {
for (var i = 0; i < self.Roles().length; i++) {
alert(self.Roles()[i].RoleID());
if (self.Roles()[i].RoleID() === data.RoleID) {
self.Role(self.Roles()[i]);
break;
}
}
}
})
}
var viewModel = new RoleViewModel();
ko.applyBindings(viewModel);
Your issue is that your are assigning items to your observable array that aren't themselves observable, so your UI is not updating when they change.
I did some renaming, as I found it confusing with so many things named 'Role', but the first change was your array setup:
var roles = [{
RoleID: ko.observable(1),
Description: ko.observable('First item')
}, {
RoleID: ko.observable(2),
Description: ko.observable('Second item')
}];
I also modified the update function:
self.update = function () {
var _Role = self.Role();
for (var i = 0; i < self.Roles().length; i++) {
if (self.Roles()[i].RoleID === _Role.RoleID) {
self.Roles()[i] = _Role();
break;
}
}
}
See the Updated Fiddle
Update:
Your json response should populate the observableArray correclty, but you may have an issue when setting it back after the update, try setting the properties rather than overwriting the element:
self.update = function () {
var _Role = self.Role();
for (var i = 0; i < self.Roles().length; i++) {
if (self.Roles()[i].RoleID === _Role.RoleID) {
self.Roles()[i].RoleID = _Role().RoleID;
self.Roles()[i].Description = _Role().Description;
break;
}
}
}
See the Updated Fiddle
I am new to knocokout.js so i have a table in which data is bind using ajax call.When user click on edit button row information is fill to a form which is on same page below the table.
after ajax call which update the data into database successfully , i am not able to show the changed value of particular object which is changed into table. If i refresh then its show new value .
Here is my html and js code .
<div id="body">
<h2>
Knockout CRUD Operations with ASP.Net Form App</h2>
<h3>
List of Products</h3>
<table id="products1">
<thead>
<tr>
<th>
ID
</th>
<th>
Name
</th>
<th>
Category
</th>
<th>
Price
</th>
<th>
Actions
</th>
</tr>
</thead>
<tbody data-bind="foreach: Products">
<tr>
<td data-bind="text: Id">
</td>
<td data-bind="text: Name">
</td>
<td data-bind="text: Category">
</td>
<td data-bind="text: formatCurrency(Price)">
</td>
<td>
<button data-bind="click: $root.edit">
Edit</button>
<button data-bind="click: $root.delete">
Delete</button>
</td>
</tr>
</tbody>
<tfoot>
<tr>
<td>
</td>
<td>
</td>
<td>
Total :
</td>
<td data-bind="text: formatCurrency($root.Total())">
</td>
<td>
</td>
</tr>
</tfoot>
</table>
<br />
<div style="border-top: solid 2px #282828; width: 430px; height: 10px">
</div>
<div data-bind="if: Product">
<div>
<h2>
Update Product</h2>
</div>
<div>
<label for="productId" data-bind="visible: false">
ID</label>
<label data-bind="text: Product().Id, visible: false">
</label>
</div>
<div>
<label for="name">
Name</label>
<input data-bind="value: Product().Name" type="text" title="Name" />
</div>
<div>
<label for="category">
Category</label>
<input data-bind="value: Product().Category" type="text" title="Category" />
</div>
<div>
<label for="price">
Price</label>
<input data-bind="value: Product().Price" type="text" title="Price" />
</div>
<br />
<div>
<button data-bind="click: $root.update">
Update</button>
<button data-bind="click: $root.cancel">
Cancel</button>
</div>
</div>
</div>
Code
function formatCurrency(value) {
return "$" + parseFloat(value).toFixed(2);
}
function ProductViewModel() {
//Make the self as 'this' reference
var self = this;
//Declare observable which will be bind with UI
self.Id = ko.observable("");
self.Name = ko.observable("");
self.Price = ko.observable("");
self.Category = ko.observable("");
var Product = {
Id: self.Id,
Name: self.Name,
Price: self.Price,
Category: self.Category
};
self.Product = ko.observable();
self.Products = ko.observableArray(); // Contains the list of products
// Initialize the view-model
$.ajax({
url: 'SProduct.aspx/GetAllProducts',
cache: false,
type: 'POST',
contentType: 'application/json; charset=utf-8',
data: {},
success: function (data) {
// debugger;
$.each(data.d, function (index, prd) {
self.Products.push(prd);
})
//Put the response in ObservableArray
}
});
// Calculate Total of Price After Initialization
self.Total = ko.computed(function () {
var sum = 0;
var arr = self.Products();
for (var i = 0; i < arr.length; i++) {
sum += arr[i].Price;
}
return sum;
});
// Edit product details
self.edit = function (Product) {
self.Product(Product);
}
// Update product details
self.update = function () {
var Product = self.Product();
$.ajax({
url: 'SProduct.aspx/Update',
cache: false,
type: 'POST',
contentType: 'application/json; charset=utf-8',
data: "{Product:" + ko.toJSON(Product) + "}",
success: function (data) {
console.log(data.d);
self.Product(null);
alert("Record Updated Successfully");
},
error: function (data) {
console.log(data);
}
})
}
// Cancel product details
self.cancel = function () {
self.Product(null);
}
}
$(document).ready(function () {
var viewModel = new ProductViewModel();
ko.applyBindings(viewModel);
});
and my webmethod which called by ajax request is as follow :
// to update product
[WebMethod]
public static testModel.Product Update(testModel.Product Product)
{
testEntities db = new testEntities();
var obj = db.Products.First(o => o.Id == Product.Id);
obj.Name = Product.Name;
obj.Price = Product.Price;
obj.Category = Product.Category;
db.SaveChanges();
return obj;
}
and JSON response of ajax call as follow
{"d":{"__type":"testModel.Product","Id":31,"Name":"12","Category":"12","Price":1350,"EntityState":2,"EntityKey":
{"EntitySetName":"Products","EntityContainerName":"testEntities","EntityKeyValues":
[{"Key":"Id","Value":31}],"IsTemporary":false}}}
Here's what's happening. Here: self.Products.push(prd) prd is just a plain javascript object with plain property values, nothing is observable. You're pushing the raw object onto the Products observableArray, which updates the DOM because Products was changed and KO is watching it. When you click 'edit', you set self.Product to that plain object and the KO updates the DOM with this object and its values because Product was changed and KO is watching it. So now your Product form below displays, you see the information, and it looks like you can edit the properties but KO won't update those property changes because KO isn't watching them. They're not observable. Change:
$.each(data.d, function (index, prd) {
//self.Products.push(prd);
self.Products.push({
Id: ko.observable(prd.Id),
Name: ko.observable(prd.Name),
Price: ko.observable(prd.Price),
Category: ko.observable(prd.Category)
});
});
General helpful tips
<div data-bind="if: Product">
This only evaluates once when you bind the viewModel to the DOM with ko.applyBindings. Since self.Product has an initial value of null KO removes this altogether.*Note: I was thinking of #if for some reason.
This works like the visible binding except when the value is false, the element and its children are removed from the DOM. So there is more DOM manipulation going on than necessary. You probably just want to hide this <div>
I would recommend changing this to:
<div data-bind="visible: Product">
Instead of this:
<input type="text" data-bind="text: Product().Name" />
<input type="text" data-bind="text: Product().Category" />
<input type="text" data-bind="text: Product().Price" />
Try this instead:
<div data-bind="with: Product">
<input type="text" data-bind="text: Name" />
<input type="text" data-bind="text: Category" />
<input type="text" data-bind="text: Price" />
</div>
Consider renaming self.Product to self.SelectedProduct to make it more clear what it is for.
I'm not sure what this is doing in the ViewModel:
//Declare observable which will be bind with UI
self.Id = ko.observable("");
self.Name = ko.observable("");
self.Price = ko.observable("");
self.Category = ko.observable("");
var Product = {
Id: self.Id,
Name: self.Name,
Price: self.Price,
Category: self.Category
};
You don't use them in the DOM. You were kind of on the right path with this though. Instead, before the ProductViewModel, create this:
function ProductModel(data) {
var self = this;
data = data || {};
self.Id = ko.observable(data.Id);
self.Name = ko.observable(data.Name);
self.Price = ko.observable(data.Price);
self.Category = ko.observable(data.Category);
}
Now instead of:
$.each(data.d, function (index, prd) {
self.Products.push({
Id: ko.observable(prd.Id),
Name: ko.observable(prd.Name),
Price: ko.observable(prd.Price),
Category: ko.observable(prd.Category)
});
});
We can just do this:
$.each(data.d, function (index, prd) {
self.Products.push(new ProductModel(prd));
});
Hopefully that will get you headed in the right direction.
There is something to change:
Replace
$.each(data.d, function (index, prd) {
self.Products.push(prd);
})
With:
$.each(data.d, function (index, prd) {
self.Products.push({
Id: ko.observable(prd.Id),
Name: ko.observable(prd.Name),
Price: ko.observable(prd.Price),
Category: ko.observable(prd.Category)
});
})
Use ko.observable to make your properties notify the view of its changes so that the view can update accordingly. This should work but not perfect because this is 2 way binding, so whenever you update the values in your div, the view model object is updated immediately and even if your ajax fails to update the data in backend, making the data out of synch between client side and server side.
For better solution. You need to have a look at protectedObservable
$.each(data.d, function (index, prd) {
self.Products.push({
Id: ko.protectedObservable(prd.Id),
Name: ko.protectedObservable(prd.Name),
Price: ko.protectedObservable(prd.Price),
Category: ko.protectedObservable(prd.Category)
});
})
Inside your self.update ajax success function, trigger a change:
success: function (data) {
var product =self.Product();
product.Id.commit();
product.Name.commit();
product.Price.commit();
product.Category.commit();
self.Product(null);
alert("Record Updated Successfully");
}
And revert if there is error:
error: function (data) {
product.Id.reset();
product.Name.reset();
product.Price.reset();
product.Category.reset();
}
Update:
Remember to change all the places with Product.Property to Product.Property() to get its property value . For example: arr[i].Price should be changed to arr[i].Price()
Add self.Products.push(data.d); to the update() functions success handler.
success: function (data) {
console.log(data.d);
self.Product(null);
self.Products.push(data.d);
alert("Record Updated Successfully");
},
You need to update the array so that it reflects in bound html.