i have two classes; users and readings. this relates to healthcare to each user has an array of readings:
/*
* Reading class
* containts health readings
*/
function Reading(date,weight,glucose)
{
var self = this;
self.date=ko.observable(date);
self.weight=ko.observable(weight);
self.glucose=ko.observable(glucose);
self.formattedWeight = ko.computed(function(){
var formatted = self.weight();
return formatted+" lb"
});
}
/*
* User class
* contains a user name, date, and an array or readings
*/
function User(name,date,readings) {
var self = this;
self.name = name;
self.date = date;
self.readingsArray = ko.observableArray([
new Reading(99,99)
]);
}
i know how to use a foreach binding to display the information for a reading or a user. but im not sure how to show the readings inside of a user?
is there a way to use a nested foreach binding or a with binding? here is my html:
<h2>Users (<span data-bind="text: users().length"></span>)</h2>
<table>
<thead><tr>
<th>User name</th><th>Date</th></th>
</tr></thead>
<!-- Todo: Generate table body -->
<tbody data-bind="foreach: users">
<tr>
<td><input data-bind="value: name" /></td>
<td><input data-bind="value: date" /></td>
<td data-bind="text: readingsArray"></td>
<td>Remove</td>
</tr>
</tbody>
</table>
<button data-bind="click: addUser">Add User</button>
<h2>Readings (<span data-bind="text: readings().length"></span>)</h2>
<table>
<thead><tr>
<th>Date</th><th>Weight</th><th>Glucose</th>
</tr></thead>
<!-- Todo: Generate table body -->
<tbody data-bind="foreach: readings">
<tr>
<td strong data-bind="text: date"></td>
<td strong data-bind="text: formattedWeight"></td>
<td strong data-bind="text: glucose"></td>
</tr>
</tbody>
</table>
and here is my model if anyone is interested. any help would be greatly appreciated! Thanks in advance!
// Overall viewmodel for this screen, along with initial state
function userHealthModel() {
var self = this;
self.inputWeight = ko.observable();
self.inputDate = ko.observable();
self.inputId = ko.observable();
self.inputGlucose = ko.observable();
// Operations
self.addUser = function(){
self.users.push(new User("",0,0,(new Reading(0,0))));
}
//adds a readings to the edittable array of readings (not yet the reading array in a user)
self.addReading = function(){
var date = self.inputDate();
var weight = self.inputWeight();
var glucose = self.inputGlucose();
if((weight&&date)||(glucose&&date))
{
self.readings.push(new Reading(date,weight,glucose));
}
else{
alert("Please complete the form!")
}
}
self.removeUser = function(userName){self.users.remove(userName)}
//editable data
self.readings = ko.observableArray([
new Reading(12,99,3),new Reading(22,33,2),
new Reading(44,55,3)
]);
self.users = ko.observableArray([
new User("George",2012),
new User("Bindu",2012)
]);
}
ko.applyBindings(new userHealthModel());
I'm not sure how you want the Readings rendered, but here is an example:
http://jsfiddle.net/jearles/aZnzg/
You can simply use another foreach to start a new binding context, and then render the properties as you wish.
Related
I want to get json array Data from service and then display this data inside table (with checkboxes)
after that i want to get data ( which was checked by user , i mean checkbox was clicked) and put it another json Array and then wrap this variable as camVariable in order to export it for second user form,
i have tried this in several ways but can’t accomplish my goal, what should i change to make it possible?
here is my code:
camForm.on('form-loaded', function() {
camForm.variableManager.fetchVariable('jsonData');
});
camForm.on('variables-fetched', function() {
$scope.jsonData = camForm.variableManager.variableValue('jsonData');
});
var selectedDocuments=$scope.selectedDocuments=[];
$scope.content = '';
$scope.isChecked = function(id){
var match = false;
for(var i=0 ; i < $scope.selectedDocuments.length; i++) {
if($scope.selectedDocuments[i].id == id){
match = true;
}
}
return match;
};
$scope.sync = function(bool, item){
if(bool){
// add item
$scope.selectedDocuments.push(item);
} else {
// remove item
for(var i=0 ; i < $scope.selectedDocuments.length; i++) {
if($scope.selectedDocuments[i].id == item.id){
$scope.selectedDocuments.splice(i,1);
}
}
}
};
camForm.on('submit', function() {
camForm.variableManager.createVariable({
name: 'selectedDocuments',
type: 'json',
value:$scope.selectedDocuments
});
});
function toJsonValue(arr) {
var myJSON = "";
var FinalResult = JSON.stringify(arr);
myJSON = JSON.stringify({FinalResult});
var json=$scope.json={};
json=JSON.parse(myJSON);
return json;
}
$scope.toggle = function (index){
if($scope.jsonData[index].hidethis == undefined){
$scope.jsonData[index].hidethis = true;
}else{
$scope.jsonData[index].hidethis = !$scope.jsonData[index].hidethis;
}
}
</script>
<h2>My job List</h2>
<div class="container">
<table name ="table" class="table table-hover" style="width:100%;" cellspacing="0">
<thead>
<tr>
<th style="width:80px; height:25px;"><input style="width:25px; height:25px;" type="checkbox" onclick="checkAll(this)"></th>
<th style="width:140px;">id</th>
<th style="width:305px;">organizationNameEN</th>
<th style="width:305px;">organizationNameGE</th>
<th> </th>
</tr>
</thead>
<tbody ng-repeat="item in jsonData" >
<tr>
<td><input type="checkbox" ng-change="sync(bool, item)" ng-model="bool" ng-checked="isChecked(item.id)" ></td>
<td><input style="width:305px;" type="number" id="id" ng-model="item.id" readonly /></td>
<td><input style="width:305px;" type="text" id="organizationNameEN" ng-model="item.organizationNameEN" required /></td>
<td><input style="width:305px;" type="text" id="organizationNameGE" ng-model="item.organizationNameGE" required/></td>
<td><button class="btn btn-default btn-xs" ng-click="toggle($index)"><span class="glyphicon glyphicon-eye-open"></span></button></td>
</tr>
<tr id="{{hideid + $index}}" ng-show="item.hidethis">
<td>
<label for="startDate" class="control-label">startDate</label>
<div class="controls">
<input style="width:105px;" id="strtDate" class="form-control" type="text" ng-model="item.startDate" required readonly/>
</div>
<br>
<label for="endDate" class="control-label">endDate</label>
<div class="controls">
<input style="width:105px;" id="endDate" class="form-control" type="text" ng-model="item.endDate" required readonly/>
</div>
</td>
</tr>
</tbody>
</table>
</div>
<script>
function checkAll(bx) {
var cbs = document.getElementsByTagName('input');
for(var i=0; i < cbs.length; i++) {
if(cbs[i].type == 'checkbox') {
cbs[i].checked = bx.checked;
}
}
}
</script>
</form>
I do something similar. In my first form, the user captures some transactions. Form 2 they double-capture (new transactions which must match the first capture) and form 3 they view they successful transactions and authorise them.
I have handled this by creating a JSON array of transactions in the first form. I save this to a process variable in the on-submit event using code like this:
camForm.on('submit', function() {
// this callback is executed when the form is submitted, *before* the submit request to
// the server is executed
// creating a new variable will add it to the form submit
variableManager.createVariable({
name: 'customVariable',
type: 'String',
value: 'Some Value...',
isDirty: true
});
I retrieve it in the subsequent forms like you do in the form-loaded/variables-fetched events.
If the JSON array data is updated in subsequent forms, I save it back to the same variable using code like this:
camForm.on('submit', function(evt) {
var fieldValue = customField.val();
var backendValue = variableManager.variable('customVariable').value;
if(fieldValue === backendValue) {
// prevent submit if value of form field was not changed
evt.submitPrevented = true;
} else {
// set value in variable manager so that it can be sent to backend
variableManager.variableValue('customVariable', fieldValue);
}
});
These code snippets are from the Camunda documentation.
First of all I am very new in Angular JS.
I have a list of items and by clicking on each one, it should be added to the table. The items are stored in a json file.
If the click event repeated several times the counter input which is located on the table must increases.
<ul class="list-inline" >
<li ng-repeat="food in foods" class="food_list">
<img class="img-box" src="images/{{ food.food_photo }}" ng-click = 'addRow(food)'><br/><span>{{food.food_name}}</span>
</li>
</ul>
<table class="table" id="table-right">
<tr>
<th>Item Name</th>
<th>Quantity</th>
<th>Price</th>
<th class="hidden-print">Delete</th>
</tr>
<tr ng-repeat="row in rows">
<td>{{row.food_name}}</td>
<td><input type="number" class="form-control" ng-model="row.food_count"></td>
<td>{{row.food_cost}}</td>
<td class="hidden-print"><button class="btn btn-info hidden-print" data-ng-click="removeRow($index)">Remove</button></td>
</tr>
app = angular.module('app',[]);
app.controller('MyCtrl', ['$scope','$http', function($scope, $http){
$scope.rows = [];
$scope.addRow = function(obj) {
$scope.foodname = obj.id;
$scope.foodprice = obj.price;
$scope.rows.push(obj);
$scope.counter++;
}
}]);
Could you please help me? Thank You.
First you have to understand that food_count property of a row object is the variable that should be updated on repetitive clicks. Updating any other $scope variables won't change row specific data because your view is bound to $scope.rows object.
Your addRow function should look like this.
$scope.addRow = function(obj) {
if($scope.rows.indexOf(obj) >= 0){ // if this obj already exist
$scope.rows[$scope.rows.indexOf(obj)].food_count++;
}
else
$scope.rows.push(obj);
}
Then the objects of $scope.foods should have a property called food_count to display.
$scope.foods = [
{food_name:'Jani',food_cost:'10', food_count:0},
{food_name:'Hege',food_cost:'8',food_count:0},
{food_name:'Kai',food_cost:'5',food_count:0}]
solution
I am displaying some data in a web app that I am getting from a SQL database using a http service. I want to be able to modify the information of that data on the same table where the data is shown. I am using angularjs and I am using the directives ng-show and ng-hide on the table. Here I show the part of the code I am talking about.
<table>
<tr>
<td><font size = 4>Servicio: </font> </td>
<td> </td>
<td>
<select class="col-sm-12" name="repeatSelect" id="repeatSelect" ng-model="currentItem.ServicioId">
<option ng-repeat="option in items.Servicio" value="{{option.Id}}"> {{option.Nombre}}</option>
</select>
</td>
</tr>
</table>
<h4>Cliente: {{getNameC(currentItem.ServicioId)}}</h4>
<br />
<button class="btn btn-primary" ng-click="editOrCreate()">Nuevo</button>
<button class="btn btn-primary" ng-click="list()">Actualizar</button>
<table class="table table-striped table-bordered">
<thead>
<tr>
<th>Cantidad</th>
<th>Tipo Concepto</th>
<th>Descripción</th>
<th>Precio Unitario</th>
<th></th>
</tr>
</thead>
<tbody>
<tr ng-repeat="item in itemsSC">
<td>
<div ng-hide="editingData[item.Id]">{{item.Cantidad}}</div>
<div ng-show="editingData[item.Id]"><input ng-model="currentItem.Cantidad" /></div>
</td>
<td>
<div ng-hide="editingData[item.Id]">{{getName(item.ServicioConceptoTipoId)}}</div>
<div ng-show="editingData[item.Id]">
<select name="repeatSelect" id="repeatSelect" ng-model="currentItem.ServicioConceptoTipoId">
<option ng-repeat="option in items.ServicioConceptoTipo" value="{{option.Id}}"> {{option.Nombre}}</option>
</select>
</div>
</td>
<td>
<div ng-hide="editingData[item.Id]">{{item.Descripcion}}</div>
<div ng-show="editingData[item.Id]"><input type="text" ng-model="currentItem.Descripcion" /></div>
</td>
<td>
<div ng-hide="editingData[item.Id]">{{item.PrecioUnitario}}</div>
<div ng-show="editingData[item.Id]"><input ng-model="currentItem.PrecioUnitario" /></div>
</td>
<td>
<button class="btn btn-xs btn-primary" ng-hide="editingData[item.Id]" ng-click="editOrCreate(item)">Modificar</button>
<button class="btn btn-xs btn-primary" ng-show="editingData[item.Id]" ng-click="saveEdit(currentItem,0)">Actualizar</button>
<button class="btn btn-xs btn-primary" ng-hide="viewField" ng-click="delete(item)">Eliminar</button>
</td>
</tr>
</tbody>
<tfoot id="total">
<tr>
<td colspan="3" class="text-right">Total:</td>
<td class="text-right">
{{total(currentItem.ServicioId) | currency}}
</td>
</tr>
</tfoot>
</table>
On my controller I am using object arrays to get the information from the databases and I am using a mirror array to keep the boolean values of the data shown on the table, so depending on the boolean value the tables shows the data or get an input for the user to modify the data.
I get the mirror array once I know the service and client related to the data I want to show and which is possible to be modified.
However, when I click on the button to modify the status of the ng-hide or ng-show object named editingData, the controllers modifies it, but the $digest run all the other functions related to the bindings of the view and returns the bool object array to its inital values.
I haven´t been able to find away to go around this normal working way of the $digest and $watches so my $editingData object is not modified to its initial values. Here I show the code of the controller related to this.
angular.module("App")
.controller("ConceptoCtrl", function ($scope, $http, $resource, serviciosConceptoFactory, serviciosConceptoTipoFactory, serviciosFactory, clientesFactory) {
$scope.list = function () {
$scope.items = serviciosConceptoFactory.query();
$scope.itemsT = serviciosConceptoTipoFactory.query();
$scope.items.ServicioConceptoTipo = $scope.itemsT;
$scope.itemsS = serviciosFactory.query();
$scope.items.Servicio = $scope.itemsS;
$scope.itemsC = clientesFactory.query();
$scope.itemsS.Cliente = $scope.itemsC;
}
//some other functions
$scope.editingData = {};
$scope.getitemsSC = function (item) {
$scope.itemsSC = [];
for (var j = 0; j < $scope.items.length; j++) {
if ($scope.items[j].ServicioId == item) {
newitem = $scope.items[j];
$scope.itemsSC.push(newitem);
}
}
for (var i = 0; i < $scope.itemsSC.length; i++) {
$scope.editingData[$scope.itemsSC[i].Id] = false;
}
}
$scope.editOrCreate = function (item) {
$scope.currentItem = item;
$scope.editingData[item.Id] = true;
}
$scope.list();
});
The {{getNameC(currentItem.ServicioId}} function shown on the html file is the one that calls the $scope.getItemsSC(item) function once it knows the services and client related to the data that will be shown and it is this function the one that initializes the boolean values for the $scope.editingData mirror array depending on the Id of the item.
The $scope.editOrCreate(item) function is the one that changes the boolean object of the specified item so that the view shows the input element for the user instead of the data. However, $digest re-runs the $scope.getItemsSC(item) function because the $watches were modified, and that´s what I want to avoid, because in this case the input elements are never shown.
I thank in advance any help provided
Instead of using the HTML to call functions when data is a available, use the $promise property attached to the resources.
$scope.list = function () {
$scope.items = serviciosConceptoFactory.query();
$scope.itemsT = serviciosConceptoTipoFactory.query();
$scope.items.ServicioConceptoTipo = $scope.itemsT;
$scope.itemsS = serviciosFactory.query();
$scope.items.Servicio = $scope.itemsS;
$scope.itemsC = clientesFactory.query();
$scope.itemsS.Cliente = $scope.itemsC;
var promiseArray = [$scope.items.$promise,
$scope.itemsT.$promise,
$scope.itemsS.$promise,
$scope.itemsC.$promise
];
$q.all(promiseArray).then(function(resultsArray) {
var items = resultsArray[0];
var itemsT = resultsArray[1];
var itemsS = resultsArray[2];
var itemsC = resultsAttay[3];
//create mirror array here
//create editingData array here
});
};
By using the .then method of the promises, the processing of the data can be delayed until it arrives from the server. This way there is no need for the HTML to call functions.
I'm having a hard time counting selected checkboxes in my application. I've tried following along some other stack overflow questions but no dice yet...if you guys have any experience with counting checkboxes, some help would be great.
HTML:
<div class="row">
<div class="col-md-12">
<table id="document-table" st-table="documents" st-safe-src="yourDisplayedCollection" class="table">
<div>Total checked: ({{selectedCounter}})</div>
<thead>
<tr>
<th>
<st-select-all all="yourDisplayedCollection"></st-select-all>
</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="document in documents">
<td><input type="checkbox" ng-model="document.isSelected"/></td>
</tr>
</tbody>
</table>
</div>
</div>
Controller:
.controller('DocumentsController', /** #ngInject */ function ($scope, restData, dateFormats, documents) {
$scope.dateFormat = dateFormats.angularDateFilter;
$scope.documents = documents.resultBag[0].documentBag;
$scope.yourDisplayedCollection = [].concat(documents.resultBag[0].documentBag);
$scope.selectAll = function (selected) {
var documents = $scope.documents;
angular.forEach(documents, function (documents) {
documents.selected = selected;
});
// Update the counter
if(selected){
$scope.selectedCounter = documents.length;
} else {
$scope.selectedCounter = 0;
}
};
EDIT:
I have a check all boxes checkbox at the top which is why i have the yourDisplayedCollection in the table as well as the ng-model="document.isSelected"
You need to rework a couple things if I am understanding the anticipated outcome correctly.
First(html):
<tr ng-repeat="document in documents">
//Bind your model directily to the selected property in your object (document)
<td><input type="checkbox" ng-model="document.selected"/></td>
</tr>
Second:
$scope.selectAll = function (selected) {
var documents = $scope.documents;
angular.forEach(documents, function (doc) {
if(doc.selected)
$scope.selectedCounter +=1;
});
};
This will give you a correct count everytime. Though your function naming is misleading. SelectAll should mean literally select all. To me it looks like your just counting.
Simplest way to do this is use Array.prototype.filter() and use length of filtered array
<input type="checkbox" ng-model="document.selected"/>
And for counter:
$scope.selectedCounter = $scope.documents.filter(function(item){
return item.selected;
}).length;
Need to be aware that you are breaking the golden rule of always using an object in ng-model.
ng-repeat creates a child scope and when you use a primitive in the child scope the parent controller can't see it change
Is it possible to manage and save the checkbox value (object) only in the controllers.js?
Thanks in advance.
I have this HTML-code (entity is an object):
<table>
<tr data-ng-repeat="entity in entities">
<td> <input type='checkbox' ng-click="toggleChecked(entity)"> {{entity.name}}</td>
</tr>
</table>
<pre>{{selectedBoxes|json}}</pre>
in my controllers.js I did this:
$scope.selectedBoxes = [];
$scope.toggleChecked = function(entity) {
if ($scope.selectedBoxes.length > 0) {
for (var box in $scope.selectedBoxes) {
if (box.name == entity.name) {
$scope.selectedBoxes.splice(box, 1);
return;
}
}
} else {
$scope.selectedBoxes.push(entity);
}
}
I am not able to print this <pre>{{selectedBoxes|json}}</pre>.
The angular method of manipulating your model actually discourages using on click to manipulate the model.
I would suggest the following:
<table>
<tr data-ng-repeat="entity in entities">
<td> <input ng-model="entity.checked" type='checkbox'> {{entity.name}}</td>
</tr>
</table>
<pre>{{selectedBoxes()| json}}</pre>
Controller:
$scope.selectedBoxes = function() {
var selected = [];
for (var entity in $scope.entities) {
if ($scope.entities[entity].checked) {
selected.push($scope.entities[entity]);
}
}
return selected;
};
Whenever a property on entity changes, selectedBoxes() will re-evaluate which will automatically update the html.