Assignment of property values in AngularJS - javascript

In AngularJS I have a problem that a variable is assigned a value of another object.
I have ng-table and this work fine
<table ng-table="tableParams" data-ng-init="getMeasureUnits()" class="table" >
<tr ng-repeat="measUnit in measureUnits" ng-click="oneEntity(measUnit)">
<td data-title="'Id'" >{{measUnit.idUnit}}</td>
<td data-title="'Name'" >{{measUnit.name}}</td>
<td data-title="'abb'" >{{measUnit.abb}}</td>
</tr>
in Controller I have function oneEntity and I got one entity from table in function but can't be assigned to another entity that which I present it in another table.
$scope.measureUnitOne = {};
$scope.oneEntity = function(entity){
$scope.measureUnitOne = entity;
$location.path("/administration/edit/measureUnit.id");
};
After function I get fine location url I everything OK byt did't display the values in table :
...
<input type="text" class="form-control" id="mesaureUnitName" data-ng-model="measureUnitOne.name" placeholder="Name">
...
Object {name: "Litar", abb: "l", last_update: 1441538332000, id_user: 123, idUnit: 2}
$$hashKey: "object:46"
abb: "l"
idUnit: 4
id_user: 123
last_update: 1441538363000
name: "Litar"
proto: Object
In first case when i Write values , table show values , in second case, that is what I got after function and noting show ... Can someone telm me where is problem ??

Related

NG-Table not working with nested data structure

I am trying to use the NG-Table library to display data to users in a web-app I'm creating, but it seems that the built in functions are not able to sort data structured like this:
var data = [
{
generalInfo:{
name: "Morty",
age: 20
}
},
{
generalInfo:{
name: "Ricky",
age: 20
}}];
The actual database I am using requires the data to be structured like this, so I can not change the structure. I tried changing my HTML to match this format, but the filter element does not allow dot notation.
My html looks like this:
<div ng-controller="appController as vm">
<table ng-table="vm.tableParams" class="table table-bordered table- striped table-condensed" show-filter="true">
<tr ng-repeat="user in $data">
<td title="'Name'" filter="{ generalFeatures.name: 'text'}" sortable="'generalFeatures.name'">{{user.generalFeatures.name}}</td>
<td title="'Age'" filter="{ generalFeatures.age: 'number'}" sortable="'generalFeatures.age'"> {{user.generalFeatures.age}}</td>
</tr>
</table>
</div>
Is there any way for me to sort data structured this way?
I found a temporary solution to this problem. I could create new properties in the parent object by looping through all of the properties in the nested object and adding them to the parent.
angular.forEach(data, function (user) {
if(user.generalInfo != null){
user.age = user.generalInfo.age;
user.name = user.generalInfo.name;
}
});

How knockout know about data-binded object if it has only its name?

I have something like:
<form action='/someServerSideHandler'>
<p>You have asked for <span data-bind='text: gifts().length'> </span> gift(s)</p>
<table data-bind='visible: gifts().length > 0'>
<thead>
<tr>
<th>Gift name</th>
<th>Price</th>
<th />
</tr>
</thead>
<tbody data-bind='foreach: gifts'>
<tr>
<td><input class='required' data-bind='value: name, uniqueName: true' /></td>
<td><input class='required number' data-bind='value: price, uniqueName: true' /></td>
<td><a href='#' data-bind='click: $root.removeGift'>Delete</a></td>
</tr>
</tbody>
</table>
<button data-bind='click: addGift'>Add Gift</button>
<button data-bind='enable: gifts().length > 0' type='submit'>Submit</button>
</form>
and
var GiftModel = function(gifts) {
var self = this;
self.gifts = ko.observableArray(gifts);
self.addGift = function() {
self.gifts.push({
name: "",
price: ""
});
};
self.removeGift = function(gift) {
self.gifts.remove(gift);
};
self.save = function(form) {
alert("Could now transmit to server: " + ko.utils.stringifyJson(self.gifts));
// To actually transmit to server as a regular form post, write this: ko.utils.postJson($("form")[0], self.gifts);
};
};
var viewModel = new GiftModel([
{ name: "Tall Hat", price: "39.95"},
{ name: "Long Cloak", price: "120.00"}
]);
ko.applyBindings(viewModel);
// Activate jQuery Validation
$("form").validate({ submitHandler: viewModel.save });
how it is happening that ko.applyBindings(viewModel); is magically making biding by name of variable? Is knockout searching it somehow by name? How the template know that this is his array/data set? I am basically .net developer so in my mind taking something "by name" is not clear. Or maybe am I wrong that this is taken by name? I read documentation but I still do not get the way how knockout connect template gifts() with array named gifts from model?
but the way this is sample from knockout main page.
http://knockoutjs.com/examples/gridEditor.html
how it is happening that ko.applyBindings(viewModel); is magically making biding by name of variable? Is knockout searching it somehow by name?
Cutting some corners here, but two things in which Javascript (not so much KO) differs from .NET, as related to your question:
All members (e.g. self.gifts) can also be accessed as if self had a string based indexer to get them (e.g. self['gifts']);
Javascript is dynamically typed, so self['gifts'] can at run time contain an array, string, observable: whatever.
So, Knockout can take your string "gifts" use it to get to the variable self["gifts"] and at run time check for its type to see if it's an array, observable y/n, etc, and choose the appropriate code path accordingly.
As for your other question:
How the template know that this is his array/data set?
Knockout is open source (though perhaps not easy to read when starting out with JS), and if you dive in to it you'll find that foreach assumes it's passed an array.

How to process a json and return a new json

What I'm trying to make is an angular app that reads in a json file and displays them, and allows users to edit the json file using html controls. Then, the user can create a new json object based on their selections and display it.
Here is a picture to help describe what I'm trying to do:
So, the user sees this, they make certain selections, e.g. lock them or delete them, then they hit create, and a new json file is returned based on which objects they have chosen to lock or delete.
At the moment I just have a standard angular app which gets and displays the json:
var app = angular.module('myApp', []);
app.controller('customersCtrl', function($scope, $http) {
$http.get("http://www.w3schools.com/angular/customers.php").then(function (response) {
$scope.myData = response.data.records;
});
$scope.createJson = function(){
// Create new json file
};
});
The body of my html/my angular app looks like this at the moment:
<div ng-app="myApp" ng-controller="customersCtrl">
<table>
<tr ng-repeat="x in myData">
<td>{{ x.Name }}</td>
<td>{{ x.City }}</td>
<td>{{ x.Country }}</td>
<td><input type="checkbox" name="lock" value="{{x.Name}}"></td>
<td><input type="checkbox" name="delete" value="{{x.Name}}"></td>
</tr>
</table>
<button ng-click="createJson()">Create</button>
</div>
Baiscally, I'm not sure if my approach is correct at the moment, and if it is, I don't really know what my next step is.
P.S. this is just test data I am using for the sake of learning/testing, it is not my data, I got it from: http://www.w3schools.com/angular/customers.php
You can try
JSON.stringify($scope.myData)
or
angular.toJson($scope.myData)
this will give you string representation of your data object. The rest is up to you, you may assign it to textarea, post it back to server (in this case, you most likely won't even need to encode it before) etc.
You should use
<td><input type="checkbox" name="lock" value="{{x.Name}}"></td>
<td><input type="checkbox" name="delete" value="{{x.Name}}"></td>
as
<td><input type="checkbox" name="lock" ng-model="x.Name"></td>
<td><input type="checkbox" name="delete" ng-model="x.Name"></td>
(Actually I didn't understand why you use string in checkbox. It should be boolean value).
By this way any change will change your $scope.myData.
On create you should take info from user and create a new JsonObject like
var newObject = {
Name: 'Name Surname',
City: 'City',
Country: 'Country'
}
And add this to your myData with;
$scope.myData.push(newObject);
I ended up creating an appropriate solution by simply creating a new and empty JSON object:
var newJson = [];
and populating it by looping through my original one and using array.push() to add the selected entries:
for (var person in $scope.myData){
if($scope.myData[person].Delete === false || $scope.myData[person].Lock === true){
newJson.push($scope.myData[person])
}
}

How to bind child array in array by using Knockout.js?

I'm using Knockout to bind data to a table:
I have obj:
obj=[{id:"1",productName:"laptop",tag:[promotion,blackfriday]},{id:"2",productName:"Samsung galaxy note III",tag:[samsung,galaxy]}]
HTML:
<table data-bind="foreach:list" id="listProduct">
<tr>
<td data-bind="text:productName"></td>
<td data-bind="foreach:obj.tag">
<p data-bind="text:tag"></p>
</td>
</tr>
</table>
JavaScript (to bind data):
ko.applyBindings({ list: obj }, document.getElementById('listProduct'));
But it only displays the product name and does not bind "tag" obj; I want Knockout to bind data as:
Product Name Tag
1 Laptop promotion
blackfriday
2 Samsung galaxy note III samsung
galaxy
based on the code you gave, there are a couple simple things that will fix this for you:
productName is misspelled
the foreach:obj.tag should be foreach:tag
the text:tag should be text:$data (see the docs on this)
your tags in the data given are not strings - so it won't work if they aren't defined elsewhere
JS:
var obj = [{
id: "1",
productName: "laptop",
tag: ["promotion", "blackfriday"]
}, {
id: "2",
productName: "Samsung galaxy note III",
tag: ["samsung", "galaxy"]
}];
ko.applyBindings({ list: obj }, document.getElementById('listProduct'));
HTML:
<table id="listProduct">
<tr data-bind="foreach:list">
<td data-bind="text:productName">test</td>
<td data-bind="foreach:tag">
<p data-bind="text:$data">test</p>
</td>
</tr>
</table>
The implementation that are you using is too odd, and I think is not correct. For example I don't know why are you retrieving the listProduct element and sending as argument to ko.applyBidning, this is not how knockout works.
You also have mistakes using inside object in the foreach binding, check out documentation to see the correct usage. Even you have a misspelled in the HTML with the productName value.
You have syntax errors inside both tag arrays, the values are string so you need to add quotes to each element.
I will show a better and clean way to do it fixing the issues mentioned above:
JS
function VM(){ //declare your VM constructor.
this.list = ko.observableArray([
{id: '1', productName: 'laptop', tag: ['promotion', 'blackfriday']},
{id: '2', productName: 'Samsung galaxy note III', tag: ['samsung', 'galaxy']}
]); //Add and observable array an set your data. If you don't need that this array be an observable just use a normal JS array.
}
ko.applyBindings(new VM()); //apply binding
HTML
<table data-bind="foreach: list">
<tr>
<td data-bind="text: productName"></td>
<td data-bind="foreach: tag">
<p data-bind="text: $data"></p>
</td>
</tr>
</table>
Check out this fiddle to see it working.

AngularJS - ng-repeat Showing single records Multiple Times

I am working with AngularJS. I am getting strange behavior from ng-repeat. I have a controller which returns me the data to ng-repeat such as:
.....
//My other JS Functions
.....
var app = angular.module('main', ['ngTable']).
controller('DemoCtrl', function($scope, ngTableParams) {
var data = [
//data in JSON form
];
$scope.tableParams = new ngTableParams({
page: 1, // show first page
count: 5 // count per page
}, {
total:data.length,
getData: function($defer, params) {
var slicedData = data.slice((params.page() - 1) * params.count(), params.page() * params.count());
alert(slicedData.length);
console.log(slicedData);
$defer.resolve(slicedData);
}
});
})
So, now one thing to note here that I am getting expected data after slicing it that I am passing to:
$defer.resolve(slicedData);
So, no issue seems here as it passes desired data.
Now, I have ng-repeat where I show data in form of tables such as:
<table ng-table="tableParams" class="table ng-table-responsive">
<tr ng-repeat="d in $data">
<td data-title="Name">
{{d.id}}
</td>
<td data-title="length">{{$data.length}}</td>
<td data-title="Age">
{{d.ciscoID}}
</td>
</tr>
</table>
So, here I am getting accurate length that is 5. But the number of records(rows) shown are 25(5*5) that each row is shown five times. Similarly, if I set the count to 10, then each record will be shown ten times.
I am unable to understand this scenario as
<td data-title="length">{{$data.length}}</td>
gives me the correct length then it should iterate correctly too.
P.S. My getData() method in the controller is called twice don't know why?
Any help/guidance regarding this will be highly appreciated. Thanks :-)
This Issue was fixed just by replacing the 'JS' and 'CSS' files with the latest ones.

Categories