Get data-bind value of button in html table - javascript

How get data-bind value in ViewsModel from Button in html table when click ?
Please help me?
Views:
<table border="1">
<thead>
<tr>
<th>
Id
</th>
<th>
Naziv
</th>
</tr>
</thead>
<tbody data-bind="foreach: customers">
<tr>
<td data-bind="text: Id_dobavljaca">
</td>
<td data-bind="text: NazivDobavljaca">
</td>
<td>
<button data-bind="click: edit, value: Id_dobavljaca">
Edit</button>
<button >
Test</button>
</td>
</tr>
</tbody>
</table>
ViewModel:
define(function (require) {
var app = require('durandal/app'), system = require('durandal/system'),
ko = require('knockout');
return {
customers: ko.observableArray([]),
activate: prikazi
}
});
function prikazi() {
var system = require('durandal/system');
var that = this;
system.log('krenu po podatke');
$.ajax({
type: 'GET',
url: '/Durandal/VratiDobavljace',
dataType: "json",
success: function (data) {
that.customers(data);
},
error: function (jq, st, error) {
alert(error);
}
});
system.log('doneo podatke');
edit = function edit1(Id_dobavljaca) {
var system = require('durandal/system');
alert(Id_dobavljaca);
var router = require('plugins/router');
router.navigate('treci/' + 123456);
};
return that.customers
}
I want to pass value ( Id_dobavljaca )in ViewsModels when click button in html table..
Thanks alot!
Martin

In DurandalJS, the object that you return from your requirejs module that is your view model is the object bound to the view. The activate function will be called when DurandalJS composes your view and view model, you can read more here.
In your current implementation the observableArray customers is a property on your view model and can be bound to your view, which is great and I assume working.
However, from looking at your current implementation you have not exposed the edit function on your view model which means it cannot be bound to the UI and used.
I have refactored your view model:
define(function(require) {
var app = require('durandal/app'),
system = require('durandal/system'),
router = require('plugins/router'),
ko = require('knockout');
var customers = ko.observableArray([]);
return {
customers: customers,
edit: function(context) {
alert(context.Id_dobavljaca);
router.navigate('treci/' + context.Id_dobavljaca);
},
activate: function() {
system.log('krenu po podatke');
return $.ajax({
type: 'GET',
url: '/Durandal/VratiDobavljace',
dataType: "json"
})
.done(function(data) { customers(data); })
.fail(function(jq, st, error) { alert(error); })
.always(function() { system.log('doneo podatke'); });
}
}
});
This refactoring exposes the customers observableArray property and the edit function. The activate function also loads your data and returns the promise back to the DurandalJS composition life cycle.
Now, you will notice that the edit function takes an argument called context, this is a knockoutjs thing. When a function is bound to the click binding the first argument passed to the function is the binding context, you can read more here.
Using this refactored view model, in your markup you want to bind your edit button to the edit function on the $root context, which is your view model.
<td>
<button data-bind="click: $root.edit">Edit</button>
<button>Test</button>
</td>
Hopefully, the snippet below can demonstrate this explanation.
var example1 = {
customers: ko.observableArray([{
Id_dobavljaca: 123,
NazivDobavljaca: 'Martin',
edit: function(context) {
alert('Id_dobavljaca: ' + this.Id_dobavljaca);
alert('Id_dobavljaca: ' + context.Id_dobavljaca);
}
}, {
Id_dobavljaca: 321,
NazivDobavljaca: 'Anish',
edit: function(context) {
alert('Id_dobavljaca: ' + this.Id_dobavljaca);
alert('Id_dobavljaca: ' + context.Id_dobavljaca);
}
}, ])
}
ko.applyBindings(example1, $('#example1')[0]);
var example2 = {
customers: ko.observableArray([{
Id_dobavljaca: 123,
NazivDobavljaca: 'Martin'
}, {
Id_dobavljaca: 321,
NazivDobavljaca: 'Anish'
}, ]),
edit: function(context) {
alert('Id_dobavljaca: ' + context.Id_dobavljaca);
}
}
ko.applyBindings(example2, $('#example2')[0]);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<p>Edit function is a property on each customer object<p>
<table id="example1" border="1">
<thead>
<tr>
<th>
Id
</th>
<th>
Naziv
</th>
</tr>
</thead>
<tbody data-bind="foreach: customers">
<tr>
<td data-bind="text: Id_dobavljaca">
</td>
<td data-bind="text: NazivDobavljaca">
</td>
<td>
<button data-bind="click: edit">
Edit</button>
<button>
Test</button>
</td>
</tr>
</tbody>
</table>
<br>
<br>
<br>
<p>Edit function is a property on the view model<p>
<table id="example2" border="1">
<thead>
<tr>
<th>
Id
</th>
<th>
Naziv
</th>
</tr>
</thead>
<tbody data-bind="foreach: customers">
<tr>
<td data-bind="text: Id_dobavljaca">
</td>
<td data-bind="text: NazivDobavljaca">
</td>
<td>
<button data-bind="click: $root.edit">
Edit</button>
<button>
Test</button>
</td>
</tr>
</tbody>
</table>
I hope this helps.

Related

SyntaxError: Unable to parse bindings with json

I'm just starting with Knockout JS, and I'm having trouble finding what is wrong here.
I'm calling a controller Web Service to get some data that I want to display in my page.
This is my ViewModel:
function ViewModel() {
var self = this;
self.MonthSalesList = ko.observableArray();
var url = 'myurl';
self.GetQueryData = function () {
$.ajax({
type: "GET",
url: url,
dataType: "json",
success: function (data) {
console.log('callback success');
console.log(data);
var observableData = ko.mapping.fromJS(data);
var array = observableData();
self.MonthSalesList(array);
},
error: function (jq, st, error) {
alert(error);
}
});
}
}
$(document).ready(function () {
ko.applyBindings(new ViewModel());
});
And in html:
<body>
<table>
<thead>
<tr>
<th>Year</th>
<th>Mes</th>
<th>Ano Atual</th>
<th>Ano Anterior</th>
<th>Variação</th>
</tr>
</thead>
<tbody data-bind="foreach: vendasMesList">
<tr>
<!-- <td data-bind="text: ko.toJSON($data)"></td> -->
<td data-bind="text: Year"></td>
<td data-bind="text: Mes"></td>
<td data-bind="text: Ano Atual"></td>
<td data-bind="text: Ano Anterior"></td>
<td data-bind="text: Variação"></td>
</tr>
</tbody>
</table>
<br/>
<input type="button" value="Get Sales" data-bind="click: GetQueryData" />
</body>
When I load the page and click on "Get Sales", I only get the first values of the json data:
The data I'm trting to get looks like this on Postman:
The only difference I see it's the numeric type of "Ano Atual".
Does anyone know what I'm doing wrong?
Thank you.
You need to change these:
<td data-bind="text: Ano Atual"></td>
<td data-bind="text: Ano Anterior"></td>
...into these:
<td data-bind="text: $data['Ano Atual']"></td>
<td data-bind="text: $data['Ano Anterior']"></td>
That's ugly, but seems to be the way to go.

How to bind JSON object with knockout on Dropdown change with html table

When I change the dropdown value, json data is change but not loads, and throws this error:
Uncaught Error: You cannot apply bindings multiple times to the same element.
How to resolve this?
$("#VehicleID").change(function () {
var categoryid = $("#VehicleTypeID option:Selected").val().trim();
var subcategoryid = $(this).val();
var url = "../Consignment/LoadratebydetailId";
$.getJSON(url, { CategoryID: categoryid, SubCategory: subcategoryid },
function (classesData) {
//var koNode = document.getElementById('fareDetailbody');
ko.cleanNode(classesData);
//ko.cleanNode($element[0]);
ko.applyBindings({
teams: classesData,
});
});
$("#rateChargeDiv").hide();
$("#rateChargeDiv").show();
});
<div id="rateDiv">
<div>
<h4>Selected Detail Changed</h4>
<table>
<thead>
<tr>
<th>name</th>
<th>cloth</th>
<th>color</th>
<th>size</th>
<th>length</th>
<th>total</th>
</tr>
</thead>
<tbody id="fareDetailbody" data-bind="foreach: teams">
<tr>
<td data-bind="text: name"></td>
<td data-bind="text: cloth"></td>
<td data-bind="text: color"></td>
<td data-bind="text: size"></td>
<td data-bind="text: length"></td>
<td data-bind="text: total"></td>
</tr>
</tbody>
</table>
</div>
<div id="close">close</div></div>
public JsonResult LoadratebydetailId(string CategoryID, string SubCategory)
{
if (CategoryID == "" || string.IsNullOrEmpty(CategoryID))
{
return Json("failure");
}
var vehCategory = this.GetratebydetailId(Convert.ToInt32(CategoryID));
var StatesData = vehCategory.
Where(cat => cat.VehicleCategoryID==Convert.ToInt32(SubCategory))
.Select(m => new
{
m.name,
m.cloth,
m.color,
m.size,
m.length,
m.total
});
return Json(StatesData, JsonRequestBehavior.AllowGet);
}

How to remove extra added row for generated JSON on button click either using AngularJS or JavaScript?

I am performing few operations like Add and Remove for my two JSON files data.
My requirement is that I need to add respective json names and show them in the table and then need to generate json object for the added/selected json names on button click. It's working fine(that I can able to show my json names on UI table and can get/generate the json data object for my selected/added json names data after button click).
But, the issue is: after generating the json object or after clicking of Send button, I can see that one row is adding extra on my UI table after clicking of Send button, I don't need this added extra row for my UI table, I need only whatever I added the json names only those should be displayed in my table after clicking of Send button. It's happening for my two json tables.(I have two Send buttons individually, one for First JSON and other for Second JSON).
I am not sure what's the wrong here ? Please help me that to display the selected json names in table on button click, that shouldn't include one extra row adding either using AngularJS or JavaScript. Thank you in advance ! Created Plnkr.
html:
<div>
<p>First Table:</p>
<table>
<thead>
<tr>
<th>Name</th>
<th>Add</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="(key, value) in myFirstJson.Testing">
<td>{{getKey(value)}}</td>
<td><button ng-click="addFirst(value)">Add</button></td>
</tr>
</tbody>
</table>
<br> <br>
<table border="1" class="table">
<thead>
<tr>
<th>Name</th>
<th>Delete</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="(key, value) in firstJsonNames track by $index">
<td>{{getKey(value)}}</td>
<td><button ng-click="deleteFirst($index)">Delete</button></td>
</tr>
<tr ng-hide="firstJsonNames.length > 0">
<td colspan="3">
<p>No Names</p>
</td>
</tr>
</tbody>
</table>
<br>
<br>
<table>
<tbody>
<tr>
<td>First Dropdown:<select ng-model="firstJsonNames.firstdropdown">
<option value="Test1">Test1</option>
<option value="Test2">Test2</option>
<option value="Test3">Test3</option>
</select><br />
</td>
</tr>
<tr>
<td>First Input:<input type="text" maxlength="50" size="50"
ng-model="firstJsonNames.firstInput" /> <br /></td>
</tr>
</tbody>
</table>
<br>
<br>
<button ng-click="generateFirstJson()">Send</button>
<br>
<br><p>Second Table:</p>
<table>
<thead>
<tr>
<th>Name</th>
<th>Add</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="(key, value) in mySecondJson.MyTest">
<td>{{value.Main.static.name}}</td>
<td><button ng-click="addSecond(value.Main.static.name)">Add</button></td>
</tr>
</tbody>
</table>
<br>
<br>
<table border="1" class="table">
<thead>
<tr>
<th>Name</th>
<th>Delete</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="name in secondJsonNames">
<td>{{name}}</td>
<td><button ng-click="deleteSecond(name)">Delete</button></td>
</tr>
<tr ng-hide="mySecondJson.MyTest.length">
<td colspan="3">
<p>No Names</p>
</td>
</tr>
</tbody>
</table>
<br>
<br>
<label>Enter Second Input Data:</label> <input
ng-model="secondJsonNames.SecondInput" placeholder="Input Text"><br>
<br>
<button ng-click="generateSecondJson()">Send</button>
<br>
<br>
</div>
app.js:
var app = angular.module('myApp', ['ui.router']);
app.controller('TestCtrl',function($scope, $http,$state,$stateParams,filterFilter,$rootScope) {
$rootScope.firstJsonNames = [];
$scope.secondJsonNames = [];
$scope.firstJsonNames.firstdropdown="Test1";
$scope.firstJsonNames.firstInput="1.5";
if($rootScope.myFirstJson == undefined)
{
$http.get('test.json').success(function(response) {
$rootScope.myFirstJson = response;
});
}
$scope.addFirst = function (name){
$rootScope.firstJsonNames.push(name);
console.log($rootScope.firstJsonNames);
};
$scope.deleteFirst = function (index){
$rootScope.firstJsonNames.splice(index,1);
};
$scope.getKey = function(item) {
return Object.keys(item)[0];
};
$scope.generateFirstJson = function(){
$rootScope.firstJsonNames.push({firstdropdown:$rootScope.firstJsonNames.firstdropdown, firstInput:$rootScope.firstJsonNames.firstInput});
console.log(angular.toJson($rootScope.firstJsonNames));
};
//second json
if($rootScope.mySecondJson == undefined)
{
$http.get('test1.json').success(function(response) {
$rootScope.mySecondJson = response;
});
}
$scope.addSecond = function (name){
$scope.secondJsonNames.push(name);
console.log($scope.secondJsonNames);
};
$scope.deleteSecond = function (name){
index = $scope.secondJsonNames.indexOf(name);
$scope.secondJsonNames.splice(index,1);
};
$scope.generateSecondJson = function(){
$scope.secondJsonNames.push({SecondInput:$scope.secondJsonNames.SecondInput});
console.log(angular.toJson($scope.secondJsonNames));
};
});
app.config(function($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise('/home');
$stateProvider
.state('home', {
url: '/home',
templateUrl: 'main.html',
controller: 'TestCtrl',
});
});
You are updating $rootScope.firstJsonNames and $scope.secondJsonNames, which are used in ng-repeat, So values are displaying in table. Use new variable for json creation.
For you are reference:
I have used
$scope.newjson2 = [];
$scope.newjson1 = [];
Plunker
http://plnkr.co/edit/r0VTaaT2rcfkiBNqyRmt?p=preview
JS:
var app = angular.module('myApp', ['ui.router']);
app.controller('TestCtrl',function($scope, $http,$state,$stateParams,filterFilter,$rootScope) {
$rootScope.firstJsonNames = [];
$scope.secondJsonNames = [];
$scope.firstJsonNames.firstdropdown="Test1";
$scope.firstJsonNames.firstInput="1.5";
$scope.newjson2 = [];
$scope.newjson1 = [];
if($rootScope.myFirstJson == undefined)
{
$http.get('test.json').success(function(response) {
$rootScope.myFirstJson = response;
});
}
$scope.addFirst = function (name){
$rootScope.firstJsonNames.push(name);
console.log($rootScope.firstJsonNames);
};
$scope.deleteFirst = function (index){
$rootScope.firstJsonNames.splice(index,1);
};
$scope.getKey = function(item) {
return Object.keys(item)[0];
};
$scope.generateFirstJson = function(){
$scope.newjson1 = angular.copy($rootScope.firstJsonNames);
$scope.newjson1.push({firstdropdown:$scope.firstJsonNames.firstdropdown, firstInput:$scope.firstJsonNames.firstInput});
console.log(angular.toJson( $scope.newjson1));
};
//second json
if($rootScope.mySecondJson == undefined)
{
$http.get('test1.json').success(function(response) {
$rootScope.mySecondJson = response;
});
}
$scope.addSecond = function (name){
$scope.secondJsonNames.push(name);
console.log($scope.secondJsonNames);
};
$scope.deleteSecond = function (name){
index = $scope.secondJsonNames.indexOf(name);
$scope.secondJsonNames.splice(index,1);
};
$scope.generateSecondJson = function(){
$scope.newjson2 = angular.copy($scope.secondJsonNames);
$scope.newjson2.push({SecondInput:$scope.secondJsonNames.SecondInput});
console.log(angular.toJson($scope.newjson2));
};
});
app.config(function($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise('/home');
$stateProvider
.state('home', {
url: '/home',
templateUrl: 'main.html',
controller: 'TestCtrl',
});
});

knockout js bindng issue when using template binding

lets say i have a following code
var Names = ['test1','test2','test3'];
function ViewModel() {
var self = this;
self.RegistraionInfo = ko.observableArray(Names);
self.ChangeSelection = function (data,event) {
fnChangeSelection(data);
}
self.tableRows = ko.observableArray([]);
self.addNewRow = function () {
self.tableRows.push(new tableRow('', self));
}
self.addNewRow();
}
function tableRow(number, ownerViewModel) {
var self = this;
self.number = ko.observable(number);
self.remove = function () {
ownerViewModel.tableRows.destroy(this);
}
ko.applyBindings(new ViewModel());
and in html
<table >
<thead>
<tr class="active">
<th></th>
<th></th>
<th></th>
<th></th>
</tr>
</thead>
<tbody data-bind="template:{name:'data-tableRow', foreach: tableRows}"></tbody>
<tfoot>
<tr>
<td >
<img id="btnAddRowProcedure1" src=#Url.Content("~/Content/img/plus.png") data-bind="click: addNewRow" />
</td>
</tr>
</tfoot>
</table>
<script id="data-tableRow" type="text/html">
<tr>
<td >
<img id="btnDelete" src=#Url.Content("~/Content/img/close.png") data-bind="click: function(){ $data.remove(); }" />
</td>
<td><select data-bind="options:$root.RegistraionInfo, , event:{ change:$root.ChangeSelection}"></select></td>
</tr>
</script>
what im trying to do here is when user clicks the #btnAddRowProcedure1 link a new tablerow will be added. and inside the table row there is a dropdown that is bound to the Names array.when the user changes the dropdown selection the ChangeSelection function is called.
The Problem is that i want knock out to send currently selected Names array element as Data but knockout sending the tableRow as data.Is there a way to overcome this problem.Im still not sure why this works like this.
UPDATE
After the #Roy J changes i was able to get this to work.but now i have stumbled upon another problem (sorry im a noob at knockout).I want to add a button when ever the user changes the selection so i have added the following code to the ViewModel
self.displayAddBtn = ko.computed(function () {
if (self.tableRows.length == 0)
{
return false;
}
return self.tableRows[self.tableRows.length-1].selected() !="";
}, self);
this code is only executed once.when the user changes the selection this is code is not executed.can some one tell me how i can make this work
You need to have a value binding on your select. That's where the new value will show up when your change function is called.
var Names = ['test1', 'test2', 'test3'];
function ViewModel() {
var self = this;
self.RegistraionInfo = ko.observableArray(Names);
self.ChangeSelection = function(data, event) {
console.debug("Changed to:", data.selected());
}
self.tableRows = ko.observableArray([]);
self.addNewRow = function() {
self.tableRows.push(new tableRow('', self));
}
self.addNewRow();
}
function tableRow(number, ownerViewModel) {
var self = this;
self.number = ko.observable(number);
self.remove = function() {
ownerViewModel.tableRows.destroy(this);
};
self.selected = ko.observable(); // new! bound to select
}
ko.applyBindings(new ViewModel());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<table>
<thead>
<tr class="active">
<th></th>
<th></th>
<th></th>
<th></th>
</tr>
</thead>
<tbody data-bind="template:{name:'data-tableRow', foreach: tableRows}"></tbody>
<tfoot>
<tr>
<td>
<img id="btnAddRowProcedure1" src=#Url.Content( "~/Content/img/plus.png") data-bind="click: addNewRow" />
</td>
</tr>
</tfoot>
</table>
<template id="data-tableRow">
<tr>
<td>
<img id="btnDelete" src=#Url.Content( "~/Content/img/close.png") data-bind="click: function(){ $data.remove(); }" />
</td>
<td>
<select data-bind="options:$root.RegistraionInfo, value:selected, event:{ change:$root.ChangeSelection}"></select>
</td>
</tr>
</template>

Call method from another ng-app in angular js

I have 2 ng-app block on same page. One for listing items, and the other one is for insert. I want to call listing function after I have finished insert.
I have tried something but I couldn't succeeded in.
I found some documents about calling functions on same ng-app but i need to call a function from another ng-app.
Here is my code, please help.
<body>
<div id="UserControllerDiv" ng-app="UserTableApp" ng-controller="UsersController" class="form-group">
<br /><br />
<p>Search : <input type="text" ng-model="search" /></p>
<table class="table table-hover">
<thead>
<tr>
<th>First Name</th>
<th>Middle Name</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="u in users | filter:search">
<td>{{ u.FirstName }} </td>
<td>{{ u.MiddleName }} </td>
</tr>
</tbody>
</table>
</div>
<br />
<div id="UserFormDiv" ng-app="UserFormApp" ng-controller="UserFormCtr" class="form-group">
<table class="form-group">
<tr>
<td>First Name</td>
<td> : </td>
<td><input type="text" ng-model="FirstName" class="" /> </td>
</tr>
<tr>
<td>Middle Name</td>
<td> : </td>
<td><input type="text" ng-model="MiddleName" /> </td>
</tr>
<tr>
<td></td>
<td></td>
<td>
<button ng-click="submit()">Save</button>
</td>
</tr>
</table>
</div>
<script>
var userTableApp = angular.module("UserTableApp", []);
userTableApp.controller("UsersController",
function UsersController($scope, $http) {
$http.get("http://localhost:10160/UserService/Users")
.success(function (response) { $scope.users = response; });
});
var userFormApp = angular.module("UserFormApp", []);
userFormApp.controller("UserFormCtr",
function UserFormCtr($scope, $http) {
$scope.submit = function () {
var dataObj = {
FirstName: $scope.FirstName,
MiddleName: $scope.MiddleName
};
var res = $http.post("http://localhost:10160/UserService/AddUser", dataObj);
res.success(function (data, status, headers, config) {
/****** Here I want to call the UsersController function of UserTableApp ************/
/* I tried the code below but it did not work */
var scope = angular.element(document.getElementById("UserControllerDiv")).scope();
scope.$apply(function () { scope.UsersController($scope, $http); });
/*************************************************************************************/
});
res.error(function (data, status, headers, config) {
alert("failure message: " + JSON.stringify({ data: data }));
});
}
});
angular.bootstrap(document.getElementById("UserFormDiv"), ['UserFormApp']);
</script>
Thank you for all your help...
Here is how you call function from other controller app.
var scope = angular.element(document.getElementById("UserControllerDiv")).scope();
scope.yourfunctionName();
And the flow will go to the Function mentioned.
For assurance you can check presence of your method in scope object in console.
You were just about right.

Categories

Resources