How to create stack bar chart in kendo ui angular - json

I'm new to angular and I'm trying to create stack bar charts using kendo UI. I'm getting normal bar rather than stack bar chart, used stack="true" also not getting the view in stack.
Here is my code :
app.component.html
<kendo-chart style="height: 150px;">
<kendo-chart-legend position="bottom" orientation="horizontal" [visible]="true"></kendo-chart-legend>
<kendo-chart-area background="#F2FAFD"></kendo-chart-area>
<kendo-chart-series>
<kendo-chart-series-item type="column" *ngFor="let item of currentFindingsData" [data]="item.items" [name]="item.value" [stack]="true">
</kendo-chart-series-item>
</kendo-chart-series>
</kendo-chart>
app.component.ts
public currentFindingsJson: GroupResult[] = [{
Value: "3"
color: "#2E75B5"
status: "CAT2 (Minor)"
}, {
Value: "10"
color: "#2E75B5"
status: "CAT1 (Minor)"
}];
this.currentFindingsData = groupBy(currentFindingsJson, [{field: 'status'}]) as GroupResult[];

You need to specify [stack]="{ type: '100%' }".
Check this document link - https://www.telerik.com/kendo-angular-ui/components/charts/series-types/bar/#toc-100-stacked-bar

Related

Is there a way to make certain elements in a list invisible with angular *ngFor?

I am building a basic inventory tracking web app with Angular and I'm running into an issue. I want my main page to immediately display the most recent inventory data. The app is in its infancy, so the inventory data is being fed to it via a mock inventory list as shown here:
import { Inventory } from './inventory';
export const INVENTORY: Inventory[] = [
{ item: 'generic', type: 'sticker', count: 14 },
{ item: 'sonny', type: 'pti', count: 9 },
{ item: 'ribbon', type: 'pti', count: 4 },
{ item: 'sonny', type: 'box', count: 56 },
{ item: 'generic', type: 'box', count: 6 },
{ item: 'salad', type: 'box', count: 12 },
{ item: 'foam', type: 'other', count: 39 },
{ item: 'glue', type: 'other', count: 41 },
{ item: 'twine', type: 'other', count: 2 }
];
The list includes a type attribute so that I can filter by type later on.
To display this list, I'm using the HTML as follows:
<ul class="inventory">
<h3>Stickers</h3>
<li *ngFor="let item of inventory">
<a *ngIf="item.type === 'sticker'>
<span class="badge">{{item.item}}</span> {{item.count}}
</a>
</li>
</ul>
As you can see, I create a list element and call *ngFor="let item of inventory" to iterate over the entire list. Next *ngIf checks if the item type is 'sticker' and if so, it writes the item.item and item.count variables to the display. The span class="badge" is for css formatting purposes only.
The problem is, this displays the blank css attributes for every item in the list, and populates the ones where type === 'sticker'. I only want to display those items with type = 'sticker', and make the rest invisible. You can see what I mean at the image below.
Web output showing css formatted list items for all items and populating only the elements of the list with type === 'sticker'
How can I do this?
To resolve this issue, Use below CSS in component.css
ul li{
list-style: none
}
Sample working ocde for reference- https://stackblitz.com/edit/angular-cql9hi?file=src/app/app.component.css
Option 2:
Use ng container and move *ngFor to ng-container and *ngIf to li element
<ul class="inventory">
<h3>Stickers</h3>
<ng-container *ngFor="let item of inventory">
<li *ngIf="item.type === 'sticker'">
<a>
<span class="badge">{{item.item}}</span> {{item.count}}
</a>
</li>
</ng-container>
</ul>
working sample code for reference - https://stackblitz.com/edit/angular-x4lzgc?file=src/app/app.component.html
ng-container allows to wrap elements like block without creating new element
Please refer this link for more details on ng-container - <ng-container> vs <template>

Correct classes not attaching to angularjs accordion and HTML not rendering correctly

I'm trying to implement something like:
http://embed.plnkr.co/3y0Rq1/
The plumbing is all connected, the groups are getting output, and each group is getting the class ng-scope, but my HTML isn't getting the class accordion-group. It's getting ng-binding instead. Also, my HTML is getting rendered as <accordion-group> and <accordion-heading> instead of as <div>s. I think that's key, but I don't know why it's happening. The application to which I'm adding the accordion already appears to have the correct file references, although the versions are newer than in the example at the link I provided. The end result is that the HTML that is rendered is just text. It's not formatted correctly and doesn't expand and contract like an accordion. Here's my code.
References in Index.cshtml (the app is being launched from ASP.NET MVC):
maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css
~/Content/dist/css/app.css
code.jquery.com/jquery-2.2.4.min.js
maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js
ajax.googleapis.com/ajax/libs/angularjs/1.5.7/angular.min.js
ajax.googleapis.com/ajax/libs/angularjs/1.5.7/angular-route.js
ajax.googleapis.com/ajax/libs/angularjs/1.5.7/angular-cookies.min.js
cdnjs.cloudflare.com/ajax/libs/angular-sanitize/1.5.7/angular-sanitize.min.js
Scripts/angular-sortable-view.js
~/Scripts/angular-auto-focus.js
Scripts/ui-bootstrap-custom-tpls-2.0.1.min.js
~/Content/dist/js/app.min.js
~/Scripts/angular-img-http-src.js
Accordion.js
(function (angular) {
angular.module("profilebuilder")
.controller("Accordion",
[
"$scope", function($scope) {
$scope.groups = [
{
title: "Dynamic Group Header - 1",
content: "Dynamic Group Body - 1",
open: false
},
{
title: "Dynamic Group Header - 2",
content: "Dynamic Group Body - 2",
open: false
}
];
}
]);
}(angular));
HTML:
<div class="SearchCriteria" ng-controller="Accordion">
<accordion>
<accordion-group ng-repeat="group in groups" heading="{{group.title}}" is-open="group.open">
<accordion-heading>
{{group.title}}
</accordion-heading>
{{group.content}}
</accordion-group>
</accordion>
</div>
Correct HTML:
Incorrect HTML:
The problem is the version you are using of the ui.bootstrap
this html will work
<uib-accordion close-others="oneAtATime">
<div uib-accordion-group class="panel-default" heading="{{group.title}}" ng-repeat="group in groups">
{{group.content}}
</div>
</uib-accordion>
Here is the link to a plknr wit example

Using #input and #output between Angular 2 child components

I have an ng-table which is a child component of my main page. When a row is clicked, it sends the information in that row via onCellClick using an EventEmitter. I'm trying to send this information to another child component. This happens to be a button which is the child of a Bootstrap 4 modal which pops up when a button on the main page is clicked. Just having trouble with the receiving and manipulation of that information.
HTML of child component table:
<ng-table [config]="config"
(tableChanged)="onChangeTable(config)"
(cellClicked)="onCellClick($event)"
[rows]="rows" [columns]="columns">
</ng-table>
HTML for the child component (this appears in the main page's HTML):
<app-datatable (row)="received($event)"></app-datatable>
Typescript for getting and sending the row's data (this.row is the EvenEmitter. data.row is the actual row that's clicked on):
#Output() row: EventEmitter<any> = new EventEmitter<any>();
public onCellClick(data: any): any {
let d = data.row.tDataPoint;
let i = data.row.tICCP;
let s = data.row.tStartDate;
let e = data.row.tEndDate;
let toSend:DataTable = new DataTable(d, i, s, e);
this.row.emit(toSend);
}
HTML for the button that is the child component of the Bootstrap 4 modal:
<button type="submit" class="btn" data-dismiss="modal" (click)="onClick($event)">Delete</button>
Typescript for the button child component:
selector: 'deletebutton'
#Input() receivedRow:DataTable;
onClick(message:DataTable){
this.sender.emit('This is from On Click Deletebutton');
console.log("On Click Deletebutton");
console.log(this.receivedRow);
for (let entry in DPS){
if (DPS[entry].tDataPoint===message.tDataPoint){
DPS.splice(parseInt(entry),1);
}
}
}
HTML of the button child component (this appears in the modal's HTML). This is what should actually be receiving the data from the clicked row as input.
<deletebutton [receivedRow]='row'></deletebutton>
Right now in my onClick method is saying receivedRow is undefined. I feel like what is missing is the coordination between [receivedRow]='row' where I have my deletebutton HTML and the onClick function call in the HTML for that child component. Overall, I just want to click a row, click the button to open the delete Boostrap Modal, and have the correct row be deleted I click the Delete button inside the modal. Let me know if something's not clear or more code is needed.
Is there actually a way to communicate between child components like this using #Input and #Output?
With angular2, your data flow should be :
- down to pass data
- up to send events
So if you really want to go this way, you should have something like that :
I think there's a better way tho :
For your app AND for your user, it'd be best to have a remove button on each line. This way, it avoid the user to be confused clicking on a row and then click on a remove button and within your code you'll be able to do something like that :
src/app.html :
<table class="table">
<tr *ngFor="let row of tableData">
<td *ngFor="let column of row.columns">
{{ column.name }}
</td>
<td (click)="deleteRow(row)"><button>X</button></td>
</tr>
</table>
<button (click)="addRow()">Add a row</button>
src/app.ts (troncated here to the class only) :
#Component({
selector: 'app',
templateUrl: `./src/app.html`,
})
export class App {
private tableData;
private cptRow = 1;
constructor() {
this.tableData = [
{
idRow: `idR${this.cptRow++}`,
columns: [
{idColumn: 'idR1C1', name: 'Column 1-1'},
{idColumn: 'idR1C2', name: 'Column 1-2'},
{idColumn: 'idR1C3', name: 'Column 1-3'}
]
},
{
idRow: `idR${this.cptRow++}`,
columns: [
{idColumn: 'idR2C1', name: 'Column 2-1'},
{idColumn: 'idR2C2', name: 'Column 2-2'},
{idColumn: 'idR2C3', name: 'Column 2-3'}
]
},
{
idRow: `idR${this.cptRow++}`,
columns: [
{idColumn: 'idR3C1', name: 'Column 3-1'},
{idColumn: 'idR3C2', name: 'Column 3-2'},
{idColumn: 'idR3C3', name: 'Column 3-3'}
]
}
];
}
deleteRow(row) {
// we can do this by reference ...
// this.tableData = this.tableData.filter(r => r !== row);
// or by ID
this.tableData = this.tableData.filter(r => r.idRow !== row.idRow);
}
addRow() {
this.tableData.push({
idRow: `idR${this.cptRow}`,
columns: [
{idColumn: `idR${this.cptRow}C1`, name: `Column ${this.cptRow}-1`},
{idColumn: `idR${this.cptRow}C2`, name: `Column ${this.cptRow}-2`},
{idColumn: `idR${this.cptRow}C3`, name: `Column ${this.cptRow}-3`}
]
});
this.cptRow++;
}
}
Here's a working Plunkr : http://plnkr.co/edit/hNhcdraoDNnI2C92TQvr?p=preview
Now, if you really want to use input/output properties, you should look for tutorials because the structure here seems a bit confused. I can help you to understand that (and it's important to understand it with angular2 !) but maybe you should give me a shout on Gitter/Angular instead of detailing Angular2 flow here :)
Somewhat of a work around is to place the Delete button component in the HTML for the table component like this:
<ng-table [config]="config"
(tableChanged)="onChangeTable(config)"
(cellClicked)="onCellClick($event)"
[rows]="rows" [columns]="columns">
</ng-table>
<deletebutton [receivedRow]='toSend'></deletebutton>
And still leave the table's tag in the main page's HTML like I had it:
<app-datatable (row)="received($event)"></app-datatable>
And now the row's data is being sent to that Delete button since it is technically a part of the child component of the main page.
Still not able to communicate between child components like I asked in my question though. But this is something close that works.

Tool bar Column Menu in kendo grid using angular js

How to put a column menu in toolbar of a kendo grid to select the columns as per need?
dataSource: $scope.kDisplayReceivedOrders,
toolbar: ["save", "cancel",
{
template:
'<button class="k-button k-button-icontext " ng-click="confirmReceivedOrder()" >Confirm</button>' +
'<button class="k-button " ng-click="printReceivedOrderDetails()">Print</button>'
}
],
You cannot insert the columnMenu froma a Kendo grid inside a toolbar because Kendo add it to the current grid.
But what you could do is a self implementation of the behavior of this menu inside your own toolbar. I have done it recently for a project.
What I have done:
An angular component.
When clicking on the component I read what columns are visible.
I do that throgh the .getOptions() and then inspecting the columns property of the object returned. The invisible columns will have a hidden=true.
Then in the template I show all the columns with a checkbox to switch the visibility.
hideColumn() and showColumn() should be attached to the action of checking or unchecking a checkbox.
Angular component controller:
init() {
if(this.grid)
this.columns = getColumns(this.grid.getOptions().columns);
}
checkbox(column) {
column.visible === true ? this._objectViewService.grid.showColumn(column.field) : this._objectViewService.grid.hideColumn(column.field);
}
A method to convert from kendo defaults to my visualization system:
function getColumns(columns) {
let cols = [];
columns.forEach(column => cols.push({title: column.title, field: column.field, visible: column.hidden !== undefined ? !column.hidden : true}));
return cols;
}
The template:
<div class="columnDropdownComponent">
<p class="title" ng-mouseover="$ctrl.init()">
<button>Columns<span class="icon-navigation-down"></span></button>
</p>
<div class="dropdown">
<div class="group">
<label ng-repeat="column in $ctrl.columns" ng-class="{'checked': column.visible}">
{{column.title}}
<input type="checkbox" ng-model="column.visible" ng-click="$ctrl.checkbox(column)">
</label>
</div>
</div>

md-chips with md-select in multi select mode

When I am trying to generate md-chips on selecting multiple values from md-select, It is not working. Does md-chips works only with autocomplete analyser and input field?
<md-chips ng-model="launchAPIQueryParams.type">
<md-select name="launchCalType" ng-model="launchAPIQueryParams.type"
multiple="true" placeholder="Launch Type"
md-on-close='applylaunchFilter("type")'>
<md-option ng-repeat="typeOption in launchTypeOptions" ng-value="typeOption[1]">
{{typeOption[0]}}
</md-option>
</md-select>
</md-chips>
The short answer: No.
<md-chips> component will only takes <input> or <md-autocomplete> into its transcluded context.
However, the same thing can be achieved with md-autocompelet.
The key is set md-min-length on <md-autocomplete> to 0 so it will auto show the menu just like what a <md-select> menu would be.
Here's an example:
// controller.js
angular
.moduel('mdChipsDemo', [])
.controller('MdChipsDemoCtrl', function() {
var vm = this;
vm.selectedOption = '';
vm.searchText = '';
vm.launchAPIQueryParams = {
types: [],
};
vm.launchTypeOptions = [
{name: 'Op1', value: 1},
{name: 'Op2', value: 2},
{name: 'Op3', value: 3},
{name: 'Op4', value: 4},
];
});
// template.html
<div ng-app="mdChipsDemo" ng-controller="MdChipsDemoCtrl as vm">
<md-chips ng-model="vm.launchAPIQueryParams.types">
<md-autocomplete
md-selected-item="vm.selectedOption"
md-search-text="vm.searchText"
md-items="typeOption in vm.launchTypeOptions"
md-item-text="typeOption.name"
md-min-length="0"
placeholder="Search for a launchTypeOptions">
<span md-highlight-text="vm.searchText">{{typeOption.name}}</span>
</md-autocomplete>
<md-chip-template>
<span>{{$chip.name}}</span>
</md-chip-template>
</md-chips>
</div>
If your ultimate goal is to have multiple select ability, <md-autocomplete> also expose <md-item-template> where you can put your <md-select> in. Check the doc for md-autocomplete and you will see.
Or if you really insist on using <select>, there's an 3rd-party component on npm calls md-chips-select which does what you want.
https://www.npmjs.com/package/md-chips-select