nested tables from json object using anguarJS - javascript

Im trying to display a json object using angular. the object may have nested object or not, so i need to evaluate in runtime.
The logic is as follows :
for each key-val (k,v):
if v is an object then: for each (k2,v2) add another nested table in the HTML_TD. if not - need to print the value in a HTML_TD
The nested object works.
The problem : when v is an object i expect the expression to evaluates to '' and print nothing (because im going to an inner loop k2,v2) but instead, even if v is an object, it print it out to the HTML_TD
code :
<table border="1">
<tr ng-repeat="(k,v) in json.properties">
<td> {{ k }} </td>
<td> {{ typeof (v) == 'object' ? '' : v }} </td>
<td>
<table>
<tr ng-repeat="(k2,v2) in v">
<td> {{ k2 }} </td>
<td> {{ v2 }} </td>
</tr>
</table>
</td>
</tr>

The typeof function is not defined on angularjs template interpolation, the template syntax is a bit limited in terms of javascript functions but you can declare it on your scope like so:
$scope.typeof = function(obj) {
return typeof(obj);
};
So that a function named typeof will be visible on your scope and your snipet will be able to get working. The bellow snipet is a simple example implementing this solution.
angular.module('myApp', [])
.controller('myController', function($scope) {
$scope.json = {
properties: {
a: 'A',
b: 'B',
c: {
a1: 'A1'
}
}
};
$scope.typeof = function(obj) {
return typeof(obj);
};
});
angular.element(document).ready(function() {
angular.bootstrap(document, ['myApp']);
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.8/angular.js"></script>
<div ng-controller="myController">
<table border="1">
<tr ng-repeat="(k,v) in json.properties">
<td>{{ k }}</td>
<td>{{ typeof(v) == 'object' ? '' : v }}</td>
<td>
<table border="1">
<tr ng-repeat="(k2,v2) in v">
<td>{{ k2 }}</td>
<td>{{ v2 }}</td>
</tr>
</table>
</td>
</tr>
</table>
</div>

I think angular parser don't allow typeof function in template.
But you can define one method in controller to get typeof.
E.g.:
$scope.getTypeof = function(value) {
return typeof value;
};
Now call this method in template code:
{{ getTypeof(v) === 'object' ? '' : v }}

Related

How to sort columns in Vue when the values to sort are the result of calculations

I've found many resources for sorting data that is already in an array but can't find anything on sorting dynamically generated data.
<table>
<thead>
<tr>
<th>Program</th>
<th>Rewards</th>
</tr>
</thead>
<tbody>
<tr v-for="program in programs" :key="program.id">
<td>{{ program.program_name }}</td>
<td>{{ pointValue(program) | percent }}</td>
</tr>
</tbody>
</table>
pointValue() is a method which calculates and returns a value which is displayed as a %. this is the Rewards column. i would like the table to be sortable by Programs and by Rewards. (Program is just a string).
Create computed array for programs using map and sort method and iterate it instead
computed: {
computedPrograms() {
return this.programs
.map(program => {
return {
...program,
value: this.pointValue(program)
}
})
.sort((a, b) => a.value - b.value)
}
}
<tr v-for="program in computedPrograms" :key="program.id">
<td>{{ program.program_name }}</td>
<td>{{ program.value | percent }}</td>
</tr>

VueJS: Check if property has value from another property

I'm currently learning Javascript (VueJS) and updated one of my existing Laravel apps. It worked pretty well so far. Still I'm in trouble at one point: I have two props (e.g. prop1 and prop2) and want to render an entry in a table differently, if a value in prop1 is also present in prop2, meaning the value is somewhere in prop2. Look at this sample code:
<tr v-for="s in list">
<td v-if="s.value1 is also present in prop2"><i class="fa fa-circle text-danger"></i></td>
<td v-else><i class="fa fa-circle text-success"></i></td>
<td>{{ s.value1 }}</td>
<td>{{ s.value2 }}</td>
</tr>
Is there a nice and short "vue-like" way to do this?
You can use the .some operator to check if a value is present in another array:
// Will return true if any items matches s.value1
prop2.some(function (item) {
return item === s.value1
});
You can add it to your Vue instance as a method or a computed property, for example:
var app = new Vue({
el: "#vue",
data: {
prop2: []
},
methods: {
checkProp2: function(val) {
return prop2.some(function (item) {
return item === val;
})
}
}
})
Then you can do something like:
<tr v-for="s in list">
<td v-if="checkProp2(s.value1)"><i class="fa fa-circle text-danger"></i></td>
<td v-else><i class="fa fa-circle text-success"></i></td>
<td>{{ s.value1 }}</td>
<td>{{ s.value2 }}</td>
</tr>
<td v-if="s.value1 === s.value2">

angularjs - ngTable not sorting

im using ngTable. Sorting is not working.
Pagination works nice and it shows all my data as I need. But I can't sort.
I'm using $data (I dont know what is for) but still can't sort.
My html:
<div class="panel-heading">
<table ng-table="vm.tableParams">
<tbody>
<tr ng-repeat="event in $data">
<td data-title="'Nombre'" sortable="'name'"> {{ event.phone ? "Tex1" : Text2 }}</td>
<td data-title="'Dia Entero'" sortable="'entero'">{{ event.allDay ? '√' : 'X' }}</td>
<td data-title="'F. Inicio'" sortable="'inicio'">{{ event.start | date:'dd-MM-yyyy' }}</td>
<td data-title="'F. Fin'" sortable="'fin'"> {{ event.end | date:'dd-MM-yyyy' }}</td>
<td data-title="'Telf.'" sortable="'telf'"> {{ event.phone ? event.phone : '--' }}</td>
</tr>
</tbody>
</table>
</div>
My js:
// My data
[{
"title":"Cerrado",
"start":"2015-12-24T23:00:00.000Z",
"allDay":true,
"backgroundColor":"#f05050",
"borderColor":"#f05050"
},
{
"title":"Abierto",
"start":"2016-04-10T04:00:00.000Z",
"end":"2016-04-10T08:00:00.000Z",
"backgroundColor":"#43d967",
"borderColor":"#43d967"
},
{
"title":"Mi Guardia",
"start":"2015-12-24T01:00:00.000Z",
"end":"2015-12-24T08:00:00.000Z",
"backgroundColor":"#5d9cec",
"borderColor":"#5d9cec"
},
{
"title":"super farmacias",
"phone":"677889966",
"address":"Calle badajoz 200",
"start":"2016-01-06T02:00:00.000Z",
"end":"2016-01-06T09:00:00.000Z",
"backgroundColor":"#dde6e9",
"borderColor":"#dde6e9",
"textColor":"#555"
}]
var data = vm.events;
vm.tableParams = new ngTableParams({
page: 1, // show first page
count: 8, // count per page
sorting: {
name: 'asc'
}
},
{
total: data.length,
counts: [],
getData: function($defer, params) {
// use build-in angular filter
var orderedData = params.sorting() ?
$filter('orderBy')(data, params.orderBy()) :
data;
$defer.resolve(orderedData.slice((params.page() - 1) * params.count(), params.page() * params.count()));
}
});
I have been trying for 2 hours with a lot of examples and changing $data for vm.values and creating other variables and stuffs.
Any idea why sort is broken?
Thanks
After checking your data, you have to modified the HTML code sortable = the object key.
Because when you sort some data in the table using ng-table, it is based on what data is displaying in the table. In this case, it will be the data you just posted. And in your data, you don't have a field called name, entero and etc. Therefore, the sort function is not working for you.
<tr ng-repeat="event in $data">
<td data-title="'Nombre'" sortable="'title'"> {{ event.phone ? "Tex1" : Text2 }}</td>
<td data-title="'Dia Entero'" sortable="'allDay'">{{ event.allDay ? '√' : 'X' }}</td>
<td data-title="'F. Inicio'" sortable="'start'">{{ event.start | date:'dd-MM-yyyy' }}</td>
...
</tr>
Usually for sorting, reverseSort feature is handy, Please try this to sort
<th>Field Name</th>

How can I pass date value to WebAPI from Angular Client?

I'm using a dynamic value to pass data from database. I'm not sure how to pass the value from the client to the server to get the expected data result.
Here the WebAPI Ctrl:
[HttpGet]
public IQueryable<getAllDayReps_Result> GetRepsByDate(DateTime datum)
{
//var dayReps = db.getAllDayReps(new DateTime(2014,05,13)).AsQueryable();
var dayReps = db.getAllDayReps(datum).AsQueryable();
return dayReps;
}
When I'm testing the commented static value, then it works fine and I'm getting the data from date 2014-05-13. But with the dynamic value I don't get data from the database.
Angular Ctrl:
//Button Send
$scope.sending = function (sel) {
$scope.selected = new Date(sel);
$scope.repDay = ResourceService.ds021.query({
'datum': $scope.selected
});
};
Service for REST:
return {
ds021: $resource(baseUrl + '/api/qr_ds021/:Id', {
Id: '#Id'
}, {})
};
View:
<div>
<input type="date" ng-model="selected" />
<button type="button" ng-click="sending(selected)">Send</button>
</div>
<div class="table-responsive">
<table class="table table-bordered table-hover">
<thead>
<tr>
<th>F_1 </th>
<th>F_2 </th>
<th>F_3 </th>
<th>F_4 </th>
<th>F_5 </th>
</tr>
</thead>
<tbody>
<tr ng-repeat="rep in repDay>
<td>{{ rep.datum }}</td>
<td>{{ rep.isin }}</td>
<td>{{ rep.NameId }}</td>
<td>{{ rep.time_quot }}</td>
<td>{{ rep.num_quot }}</td>
</tr>
</tbody>
....
How you can see I'm typing an value in the input field. The ngModel value will sending with the button "send" to the service. But something is wrong in the service and I don't know what..
EDIT:
Here is the method from the Context.tt:
public virtual ObjectResult<getAllDayReps_Result> getAllDayReps(Nullable<System.DateTime> datumOut)
{
var datumOutParameter = datumOut.HasValue ?
new ObjectParameter("DatumOut", datumOut) :
new ObjectParameter("DatumOut", typeof(System.DateTime));
return ((IObjectContextAdapter)this).ObjectContext.ExecuteFunction<getAllDayReps_Result>("getAllDayReps", datumOutParameter);
}

Unbinding ng-repeat scope

I have two <tr>s and an ng-repeat on each, but both perform the same operation on their child elements, like so:
<tr ng-repeat="item in data : filterFunc" ng-if="mode === 'something'">
<td>{{item.name}}</td>
</tr>
<tr ng-repeat="item in data : filterFunc" ng-if="mode === 'somethingelse'">
<td>{{item.name}}</td>
</tr>
Imagine, there are two types of data sets and which one is to be rendered is decided by the mode property at run time. So, either the first <tr> is rendered in the DOM or the other one.
Initially the first <tr> will be rendered and the associated filterFunc function will work properly. There's a simple drop down which has two options, one each for the two modes. If you select the other mode, the second <tr> will be rendered and first one will be removed from the DOM.
The problem is, the filterFunc now is bound to both the <tr>s and operates on both of them.
How do I unbind the scope or watchers for the first one let it be bound only to the second one? or any one of them at any point of time? Here's the fiddle http://jsfiddle.net/6kx4ojL4/
Note: For the sake of simplicity, I have simply returned the passed-in data object as-is in filterFunc. Check the output in browser console. It gets called twice, i.e. for both data sets.
It is not clear what you want to do exactly from your description. My first thought is that you could separate your modes in ng-if, say, use mode1 and mode2, so you can control two <tr>s separately..
Use ng-show instead of ng-if
<tr ng-repeat="item in data : orderBy: 'name'" ng-show="mode === 'something'">
<td>{{item.name}}</td>
</tr>
<tr ng-repeat="item in data : orderBy: 'name'" ng-show="mode === 'somethingelse'">
<td>{{item.name}}</td>
</tr>
How about this. Check this JSFiddle: http://jsfiddle.net/vxcjw45d/1/
If it's not what are you looking for tell me - I will delete it :)
HTML:
<body ng-app="myApp">
<table ng-controller="myController">
<tr ng-repeat="item in data | orderBy: 'name'"
ng-if="mode === 'something'">
<td>{{ item.name }}</td>
</tr>
<tr ng-repeat="item in data | orderBy: 'name'"
ng-if="mode === 'somethingelse'">
<td>{{ item.age }}</td>
</tr>
<tr>
<td>
<button ng-click="changeMode()">
Change Mode
</button>
</td>
</tr>
</table>
</body>
JS:
var myApp = angular.module('myApp', []);
myApp.controller('myController', function($scope) {
$scope.data = [
{ name: 'John', age: 21 },
{ name: 'Doe', age: 33 }
];
$scope.mode = 'something';
$scope.changeMode = function() {
if ($scope.mode === 'something') {
$scope.mode = 'somethingelse';
} else if ($scope.mode === 'somethingelse') {
$scope.mode = 'something'
}
};
});

Categories