replacing null data with string "null" in angular js - javascript

I have to display table in html page using ng-repeat.
most of the entries in table have null data but i am unable to replace null with either empty space or string null. I tried {{ row || 'null' }} but it didnt help. When it generate table it mess it up completely if rows have large number of nulls.
<table>
<tr>
<th ng-repeat="colname in sqldata.collist">{{colname}}</th>
</tr>
<tr ng-repeat="rows in sqldata.tablist">
<td ng-repeat="row in rows">{{ row || 'null' }}</td>
</tr>
</table>

How about the old ng-show and ng-hide trick to show something if a value is 'null'.
Replace
{{ row || 'null' }}
with
<div ng-show="row">{{row}}/div>
<div ng-hide="row">null</div>

A better option would be to use a filter. This means no duplicated DOM elements, a hidden and shown element. It also keeps logic out of your view.
Plus it makes the 'no data' message standard across your application as you can use it in almost all data binding cases.
<div ng-app="test" ng-controller="ClientCtrl">
<div ng-repeat="elem in elems">
{{elem | isempty}}
</div>
</div>
And your JavaScript
angular.module('test', []).filter('isempty', function() {
return function(input) {
return isEmpty(input) ? 'No Value' : input;
};
function isEmpty (i){
return (i === null || i === undefined);
}
})
http://jsfiddle.net/5hqp5wxc/
Docs: https://docs.angularjs.org/guide/filter

Another option is ng-if
<table>
<tr>
<th ng-repeat="colname in sqldata.collist">{{colname}}</th>
</tr>
<tr ng-repeat="rows in sqldata.tablist">
<td ng-repeat="row in rows">
<span ng-if="row" >{{ row }} </span>
<span ng-if="!row" > null </span>
</td>
</tr>
</table>

Related

Vue, accessing data that's in a different v-for loop

I have a table body in my Vue application where I've got one section of rows being built by a loop around a data object. I then have a separated section that is using a different data object, however, I need to compare a value from it to a value from the other loop in order to get conditional styling
I'm wondering if there is a way where I can send data from the value portion of the first for loop into a method call at the time of that v-for so that I can access it in the summary loop, if that makes sense
Here's the table:
<tbody v-if="selected === 'Stores'">
<tr v-for="(value, manager) in managerNumbers" :key="manager"> <!--Here is where I'm wondering if I can send value to a method call-->
<td v-for="date in dates" :key="date" >
<div v-for="(dataForDate, dateVal) in value.dates" :key="dateVal">
<div v-if="dateVal == date ">
#{{dataForDate.total_categories}}
</div>
</div>
</td>
</tr>
<tr><td colspan="10"></td></tr>
<tr><td colspan="10"></td></tr>
<tr>
<th>
Summary
</th>
<div v-for="store in activeStore" :key="store">
<th :style="'background: ' + (value.qty > store.qty ? '#000' : '#fff')">#{{ store.stock_num }}</th>
</div>
</tr>
</tbody>
You can use a computed method to create a lookup table between both activeStore and managerNumbers and loop over that.
get activeStoreAndManagerNumbers () {
return managerNumbers.map((value, index) => {
return {
value,
store: activeStore[index]
}
})
}
Now you can just loop over this array for both of your v-for:
v-for="(obj, index) in activeStoreAndManagerNumbers"
Now obj.value.qty and obj.store.qty are available in the same loop.

How to bind an object to HTML table in Vue.js, where its properties are dynamically created?

I am using vue.js library for front-end development.
I came a cross a scenario where my JavaScript method returns a list, which has objects, object's number of properties can change each time after method execution.
example my list can contain these type of objects in 2 different executions.
var obj = {
Name : "John",
2020-Jan: 1,
2020-Jul: 2
}var obj = {
Name: "John",
2020-Jan: 1,
2020-Jul: 2,
2021-Jan: 3,
2021-Jul: 4
}
Since Property name is dynamically changes is there any way to bind to HTML ?
<div >
<table>
<thead>
<tr>
<th v-for ="row in Result.Headers">
{{row}}
</th>
</tr>
</thead>
<tbody>
<tr v-for="item in Result.Data ">
<td>
{{item.2020-Jan}} // Because don't know the number of properties until run time
</td> // No of <td/>'s can change on no of properties.
<td> // exactly don't know how many <td>'s needed there.
{{item.2020-Jul}}
</td> <td>
{{item.2021-Jan}}
</td>
</tr>
</tbody>
</table>
</div>
Is there way to bind these type of object to fronted in vue.js ?
You need to loop over the item's keys again. This will show all the values in the object
<tbody>
<tr v-for="item in Result.Data ">
<td v-for="(value, key, index) in item">
{{value}}
</td>
</tr>
</tbody>
If you want to filter some of them, for instance check that the keys are valid dates you need to add a v-if and use Date.parse to check for this.
<tbody>
<tr v-for="item in Result.Data ">
<td v-for="(value, key, index) in item" v-if="Date.parse(key) !== NaN">
{{value}}
</td>
</tr>
</tbody>
if u wana show all attr-> u can use this:
<ul v-for="item in Result ">
<li v-for="(value,key,index) in item">{{value}}</li>
</ul>
if u wana show all days u can use v-if and compute to complete youself fillter
<div id="app">
<ul v-for="item in Result" >
<li v-for="(value,key,index) in item" v-if="canShow(key)"> index:{{index}}------ key: {{key}} ------ value:{{value}} </li>
</ul>
</div>
<script>
var vue=new Vue({
el:'#app',
data:{
Result:[{
name: 'SkyManss',
2020-Jan: 1,
2020-Jul: 2
},{
name: 'SkyManss2',
2020-Jan: 1,
2020-Jul: 2,
2021-Jan: 3,
2021-Jul: 4
}]
},
computed:{
canShow(){
return function(skey){
return skey.indexOf('-') > -1;
}
}
}
});
</script>
after some research and some of your suggestions I came up with an answer.
<div>
<table>
<thead>
<tr>
<th v-for ="row in Result.Headers">
{{row}}
</th>
</tr>
</thead>
<tbody>
<tr v-for="item in Result.Data ">
<td v-for="row in Result.Headers">
{{item[row]}}
</td>
</tr>
</tbody>
</table>
</div>
Javascript code
this.Result.Headers = Object.keys(result.data[0]);
this.Result.Data = result.data;
But this code only worked for the first time. second time data didn't get updated. So I updated JavaScript code to following code.
Vue.set(self.Result, 'Headers', []);
Vue.set(self.Result, 'Result', []);
this.Result.Headers = Object.keys(result.data[0]);
this.Result.Data = result.data;
Vue does not allow dynamically adding new root-level reactive properties to an already created instance. That I got to know from following post.
vue.js is not updating the DOM after updating the array
Thank You All !!!

Angularjs: Pulling display data from $scope scenario

I have the following ng-repeat call which displays flat 'AVAILABLE' or 'FULL' on the front end. Need to make it more dynamic by modifying html to read from $scope.
<tbody>
<tr ng-repeat="hour in workhours">
<td >{{hour}}:00 - {{hour+1}}:00</td>
<td ng-class="{'full' : !entry.HoursAvailable.includes(hour)}"
ng-click="checkSlotAvailability(hour, jobLength, entry, data)"
ng-repeat="entry in data.calendar" >
{{entry.HoursAvailable.includes(hour) ? 'AVAILABLE' : 'FULL'}}
</td>
</tr>
</tbody>
In place of 'AVAILABLE', I want to read the response from $scope.data.response in controller.js
You can do this
<span ng-if="entry.HoursAvailable.includes(hour)">
{{ data.response }}
</span>
<span ng-if="!entry.HoursAvailable.includes(hour)">
FULL
</span>

nested ng-repeat that one depend on the other

I have an issue with angular, I want to use two nested ng-repeat in a data table where the first get the data, and the second get the name of field to be retrieved from the data (retrieved in the first ng-repeat)
here is what I tried to do with code :
<table md-table flex-order-gt-sm >
<thead md-head>
<tr md-row >
//1st : get the name of fields, not a problem
<th md-column ng-repeat="field in fields">{{item.name}}</th>
</tr>
</thead>
<tbody md-body>
<tr md-row ng-repeat="item in items">
<td md-cell ng-repeat="field in fields" >
//here is the problem I want to get the item that it's field name is field
{{item.{{field}} }}</td>
</tr>
</tbody>
</table>
for example if fields contain :{'a','b','c'}
and items contains {'a':'1','b':'2','c':'3'};
I want for example for the 1st iteration of {{item.{{field}} }} to return 1
Use toString() to retrieve the scope data in an scope object.
<tr md-row ng-repeat="item in items">
<td md-cell ng-repeat="field in fields" >
{{item[field.toString()]}}
</td>
</tr>
Here is the plunker
As an alternative you could also use a filter:
<td md-cell ng-repeat="field in fields | filter: { name: 'field' }">
</td>
You need to get fields collection according to item of items collection after
getFieldsByItem(item)
Then you can get field from fields collection
{{field}}

Combine ngRepeat and conditional directive

I'm trying to learn some AngularJS for a project. In my model I have a list of elements that can be of different types. Now I want to show them in a table that looks similar to this example:
<table>
<tr><td>nameA</td><td>...</td><td>...</td></tr> <!-- elements of type A -->
<tr><td>nameB</td><td colspan="2">...data...</td></tr> <!-- elements of type B -->
<tr><td>nameC</td><td>...</td><td>...</td></tr> <!-- elements of type A -->
</table>
If the element is of type A, it should be displayed like the first and third table row, if it is of type B, it should be displayed like the second table row.
How do I achieve this with AngularJS? I started with something like the following:
<table>
<tr ng-repeat="elem in data.elements | orderBy:'name'">
<td>{{ elem.name }}</td><td>...</td><td>...</td>
</tr>
</table>
But now all the table rows have the same format of course. I'm not sure how to combine this with some type of conditional directive to use different templates for the table row, depending on elem.type. I would need something like this:
<table>
<tr ng-repeat="elem in data.elements | orderBy:'name'">
<pseudo-tag ng-if="elem.type == 'typeA'">
<td>{{ elem.name }}</td><td>...</td><td>...</td>
</pseudo-tag>
<pseudo-tag ng-if="elem.type == 'typeB'">
<td>{{ elem.name }}</td><td colspan="2">...data...</td>
</pseudo-tag>
</tr>
</table>
What is the AngularJS-y way to achieve this?
You shouldn't need a pseudo-tag because ng-if can be applied directly to td. Something like this should work:
<table>
<tr ng-repeat="elem in data.elements | orderBy:'name'">
<td ng-if="elem.type == 'typeA' || elem.type == 'typeB'">{{ elem.name }}</td>
<td ng-if="elem.type == 'typeB'" colspan="2">...data...</td>
<td ng-if="elem.type == 'typeA'">...</td>
...
</tr>
</table>

Categories