I have the following problem. I wanna repeat menu links. But the program doesn't create the corresponding click handler.
View:
//view is created by Angular Material
<md-menu-item ng-repeat="mItem in ::menuItems">
<md-button ng-click="mItem[action]">
<md-icon>{{ ::mItem.icon }}</md-icon>
{{ ::mItem.name }}
</md-button>
</md-menu-item>
Ctrl:
$scope.menuItems = [
{ icon: 'mode_edit', name: 'Edit', action: 'clickEdit()' },
{ icon: 'delete', name: 'Delete', action: 'clickDelete()' }
];
$scope.clickEdit = clickEdit;
$scope.clickDelete = clickDelete;
function clickEdit() {
$log.info('edit clicked');
}
function clickDelete() {
//code...
}
What I need to do to get the handlers in ngClick?
I think it's best to keep that logic in a service like this:
//view is created by Angular Material
<md-menu-item ng-repeat="mItem in ::menuItems">
<md-button ng-click="action(mItem.action)">
<md-icon>{{ ::mItem.icon }}</md-icon>
{{ ::mItem.name }}
</md-button>
</md-menu-item>
$scope.menuItems = [
{ icon: 'mode_edit', name: 'Edit', action: 'edit' },
{ icon: 'delete', name: 'Delete', action: 'delete' }
];
$scope.action = function(actionName){
// call service
}
Related
I have a problem when I want to parse the data, which get from http call, and parsing it to chart data that located ngoninit. When page reload, the chart is show blank data. Can you help me to solve this problem? I am using Chartist.js and Angular 4.
The html:
<div class="col-md-4">
<lbd-chart
[title]="'Email Statistics'"
[subtitle]="'Last Campaign Performance'"
[chartClass]="'ct-perfect-fourth'"
[chartType]="emailChartType"
[chartData]="emailChartData"
[legendItems]="emailChartLegendItems"
[withHr]="true"
[footerIconClass]="'fa fa-clock-o'"
[footerText]="'Campaign sent 2 days ago'">
</lbd-chart>
</div>
The ngOnInit:
async ngOnInit() {
console.log('Halo from ngOnInit');
const data1 = await this.serviceDashboard.getAllGeografika().toPromise();
const data2 = await this.serviceDashboard.getAllHistorika().toPromise();
const data3 = await this.serviceDashboard.getAllKeramologika().toPromise();
this.data1 = data1.length;
this.data2 = data2.length;
this.data3 = data3.length;
this.emailChartType = ChartType.Pie;
this.emailChartData = {
series: [this.data1, this.data2, this.data3]
};
this.emailChartLegendItems = [
{ title: 'Open', imageClass: 'fa fa-circle text-info' },
{ title: 'Bounce', imageClass: 'fa fa-circle text-danger' },
{ title: 'Unsubscribe', imageClass: 'fa fa-circle text-warning' }
];
}
1) I would prefer rxjs over async/await paradigma.
ngOnInit() {
console.log('Halo from ngOnInit');
const data1$ = this.serviceDashboard.getAllGeografika();
const data2$ = this.serviceDashboard.getAllHistorika();
const data3$ = this.serviceDashboard.getAllKeramologika();
this.chartContext$ = combineLatest([data1$, data2$, data3$])
.pipe(
map(([d1, d2, d3]) => {
return {
emailChartType: ChartType.Pie,
emailChartData: [d1, d2, d3],
emailChartLegendItems = [
{ title: 'Open', imageClass: 'fa fa-circle text-info' },
{ title: 'Bounce', imageClass: 'fa fa-circle text-danger' },
{ title: 'Unsubscribe', imageClass: 'fa fa-circle text-warning' }
]
}
}
)
)
}
// And template
<div class="col-md-4">
<lbd-chart
*ngIf="chartContext$ | async as chart"
[title]="'Email Statistics'"
[subtitle]="'Last Campaign Performance'"
[chartClass]="'ct-perfect-fourth'"
[chartType]="chart.emailChartType"
[chartData]="chart.emailChartData"
[legendItems]="chart.emailChartLegendItems"
[withHr]="true"
[footerIconClass]="'fa fa-clock-o'"
[footerText]="'Campaign sent 2 days ago'">
</lbd-chart>
</div>
2) Anyway 1) maybe won´t help you. Chartist.js and Angular 4? You should maybe consider better chart library and current (9) version of Angular. D3.js has never failed anyone (but you would have to create your own chart components :-))
3) Have you tried just put dummy fake data in your chart without querying the API and see if it works?
I have created an ionic alert to decline a request. I want the user to input a reason for declining the request before they hit confirm. I then would like to save this data into my database and have a method (declineRequest) setup to do so.
The method is working for declining the request. The issue is how to save the alert 'Notes' input field into the database, and how to make sure the declineRequest method is only run when 'confirm' is clicked.
Here is the code:
The HTML:
<ion-list>
<ion-card *ngFor="let r of requests; let i = index">
<ion-item>
<h2>{{r.userId}}</h2>
<p>{{r.requestDetail}}</p>
<p>{{r.fromDateTime}} to {{r.toDateTime}}</p>
<p>{{r.type}}</p>
</ion-item>
<ion-card-content>
<button class="approve" ion-button icon-left color="secondary" (click)="approveAlert(r.id)">
<ion-icon name="checkmark"></ion-icon>
Approve
</button>
<button class="decline" ion-button icon-left color="danger" (click)="declineAlert(r.id)">
<ion-icon name="close"></ion-icon>
Decline
</button>
</ion-card-content>
</ion-card>
</ion-list>
The TS:
declineAlert(requestId) {
const alert = this.alertCtrl.create({
title: 'Confirm Request Declined',
subTitle: 'Notes:',
inputs: [
{
name: "Note",
type: "text",
placeholder: 'Please enter reasons'
}],
buttons: [ { text:"Cancel"
},
{ text: "Confirm",
handler: data => {
console.log(JSON.stringify(data));
console.log(data.Note);
}
}],
cssClass: 'alertCustomCss'
});
alert.present();
console.log(requestId);
let notes = Note;
this.declineRequest(requestId, notes);
}
I have tried different methods but cannot seem to get the text from the decline 'notes' to save.
Any help would be greatly appreciated.
As Keval pointed out you just need to use your method inside the handler like so:
declineAlert(requestId) {
const alert = this.alertCtrl.create({
title: 'Confirm Request Declined',
subTitle: 'Notes:',
inputs: [
{
name: "Note",
type: "text",
placeholder: 'Please enter reasons'
}],
buttons: [ { text:"Cancel"
},
{ text: "Confirm",
handler: data => {
this.declineRequest(requestId, data.Note);
// additional steps like pop() page etc
}
}],
cssClass: 'alertCustomCss'
});
alert.present();
}
Try with my working code
let alert = this.alertCtrl.create({
title: 'Confirm Request Declined',
inputs: [
{
type: 'textarea',
name: 'Message',
placeholder: 'Please enter reasons',
},
],
buttons: [
{
text: 'Yes',
handler: data => {
var message = data.Message;
//Here is Api call
}
},
{
text: 'No',
role: 'cancel',
handler: data => {
var message = data.Message;
//Your logic
}
}
]
});
alert.present();
I am using the angular datatables module in my project and i configured a function using the rowrollback function to perform actions when clicked on the row. but when using that i can't click on buttons in my row, like actions designed for each row (e.g delete modify client ).
I tried not to add the Actions column in my dtconfig object but it made my datatable not get triggered.
here is my code :
dtOptions :
dtOptions = {
pagingType: 'full_numbers',
pageLength: 10,
columns: [{
title: 'Current Owner',
data: 'CurrentOwner'
},{
title: 'Doc Hash',
data: 'hash'
},{
title: 'Doc Name',
data: 'name'
},{
title: 'Doc Owner',
data: 'DocumentOwner'
},{
title: 'Time Stamp',
data: 'Timestamp'
},{
title: 'Actions',
data: 'actions'
}],
rowCallback: (row: Node, data: Object |any[] , index: number) => {
try{
const self = this;
// Unbind first in order to avoid any duplicate handler
// (see https://github.com/l-lin/angular-datatables/issues/87)
$('td', row).unbind('click');
$('td', row).bind('click', () => {
let X ={};
Object.assign(X,data);
console.log(X)
console.log(this.Certificates[index]);
self.DetailedCertificate=this.Certificates[index];
$(this.detailRef.nativeElement);
$(this.detailRef.nativeElement).modal("show");
});
return row;
}
catch (e){
console.error("error"+e);
}
}
HTML Table :
<tr *ngFor="let row of dataRows" class=".row" >
<td style="text-overflow: ellipsis; overflow-wrap: break-word">{{row.CO}}</td>
<td>{{row.KC}}</td>
<td>{{row.DocName}}</td>
<td>{{row.DocOwner}}</td>
<td>{{row.TimeStamp}}</td>
<td class="text-right">
<button class="btn btn-lg btn-simple btn-info btn-icon" (click)="CO(row.KC,row.DocOwner)"><i class="material-icons">person_pin_circle</i></button>
<button class="btn btn-lg btn-simple btn-danger btn-icon" (click)="RC(row.KC,row.DocOwner)"><i class="material-icons">close</i></button>
</td>
</tr>
Here is an example of a table in angular that accomplishes what you want.
import { Component } from '#angular/core';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
title = 'app';
dataRows: any[] = [
{ kc: 'kc1', docName: 'Document 1', docOwner: 'Johnny', timeStamp: 'last week'},
{ kc: 'kc2', docName: 'Document 2', docOwner: 'Jacob', timeStamp: 'yesterday'},
{ kc: 'kc3', docName: 'Document 3', docOwner: 'Jingleheimer', timeStamp: 'today'},
{ kc: 'kc4', docName: 'Document 4', docOwner: 'Schmidt', timeStamp: 'tomorrow'}
];
buttonInRowClick(event: any): void {
event.stopPropagation();
console.log('Button in the row clicked.');
}
wholeRowClick(): void {
console.log('Whole row clicked.');
}
}
<table>
<tr>
<th>KC</th>
<th>Doc Name</th>
<th>Doc Owner</th>
<th>Time Stamp</th>
<th>Button</th>
</tr>
<tr *ngFor="let row of dataRows" (click)="wholeRowClick()">
<td>{{row.kc}}</td>
<td>{{row.docName}}</td>
<td>{{row.docOwner}}</td>
<td>{{row.timeStamp}}</td>
<td><button (click)="buttonInRowClick($event)">do thing</button></td>
</tr>
</table>
This line adds the function call to every row that ngFor generates.
<tr *ngFor="let row of dataRows" (click)="myFunction()">...</tr>
The key to making sure the click events on buttons within the rows don't interfere with the overall row click is to add
event.stopPropagation();
in the functions that the nested buttons call.
You can invoke the CO() function by using jquery call in AfterViewInit interface like below. And get 'row.KC' value by setting it as id in html
ngAfterViewInit(){
var _thisDoc = this;
$('#user-table').on('click', '.btn-circle', function(){
_thisDoc.CO(this.id);
});
}
CO(e) {
console.log(e); //row.KC value
}
I'm new to ionic and having a hard time to get data from alert inputs and showing them to another page. I'm making a button that shows alert, then you can input the time (I don't know how to use datetime in ionic) and a randomizes of number. Then showing all inputs to another page.
HTML
<ion-content padding>
<ion-grid>
<button ion-button id="id" (click)="sample;" [disabled]="disabled">1</button>
</ion-grid>
</ion-content>
TS
Ground1(bname:string){
let alert = this.alertCtrl.create({
title: 'Confirm Park',
message: 'Do you want to park this slot?',
inputs: [
{
name: 'Time',
placeholder: 'Input Time',
},
{
name: 'Code',
placeholder: 'Random Number'
},
{
name: 'Date',
placeholder: 'MM/DD/YY'
}
],
buttons: [
{
text: 'Cancel',
role: 'cancel',
handler: () => {
console.log('Cancel clicked');
}
},
{
text: 'Confirm',
handler: data => {
this.buttonColor1 = 'red'
console.log('Confirm clicked');
this.disabled = true;
console.log(JSON.stringify(data));
this.navCtrl.push(ResultPage, {result:name}, alert);
}
}
]
});
alert.present();
Alerts can also include Radios, checkboxes and text inputs , but they cannot be mixed. In addition, you can not use datetime picker in it.
Do note however, different types of "text"" inputs can be mixed, such as url, email, text, etc. If you require a complex form UI which doesn't fit within the guidelines of an alert.
If you want to use different inputs such as datetime or html inputs it is recommended that you must create the form within a modal instead.
datetime.html
<ion-header>
<ion-navbar>
<ion-title>DateTime</ion-title>
</ion-navbar>
</ion-header>
<ion-content padding>
<ion-item>
<ion-label>Full Date</ion-label>
<ion-datetime displayFormat="DDDD MMM D, YYYY" min="2005" max="2100" [(ngModel)]="myFullDAte"></ion-datetime>
</ion-item>
<ion-item>
<ion-label>Time</ion-label>
<ion-datetime displayFormat="hh:mm A" [(ngModel)]="myTime"></ion-datetime>
</ion-item>
</ion-list>
</ion-content>
ts file
import { ModalController, NavParams } from 'ionic-angular';
#Component(...)
class MyPage {
constructor(public modalCtrl: ModalController) { }
presentModal() {
let myModal = this.modalCtrl.create(Datetime);
profileModal.present();
}
}
You can get the data from the fields in the confirm handler. You should be able to just pass the data variable to the next page, which should include data.Time, data.Code and data.Date.
this.navCtrl.push(ResultPage, {result: data});
On your ResultPage you can just use navParams (http://ionicframework.com/docs/api/navigation/NavParams/) to retrieve the result data that you passed.
result = this.navParams.get('result');
I'm trying to change an ng-click event by loading an item.list with the command inside my main app.js file. The item.list looks something like this:
$scope.list = [
{
label: 'Controls',
icon: 'fa fa-sliders fa-fw 4x',
name: 'Controls',
link: '#/ctrlPage',
move: 'console.log("On control page.")'
},
{
label: 'Lights',
icon: 'fa fa-film fa-fw 4x',
name: 'Lights',
link: '#/lightPage',
move: 'connection.send("control Closer");'
},
{
label: 'Queue',
icon: 'fa fa-users fa-fw 4x',
name: 'Queue',
link: '#/queuePage',
move: 'connection.send("control Closer");'
},
{
label: 'Settings',
icon: 'fa fa-cogs fa-fw 4x',
name: 'Settings',
link: '#/settingsPage',
move: 'connection.send("control Closer");'
}
On my index.html page, I have this setup:
<md-list>
<md-list-item ng-repeat="item in list" md-ink-ripple="#3F51B5" class="pointer">
<a href='{{item.link}}' ng-click='{{item.move}}'>
<span aria-label="{{item.label}}" class="{{item.icon}} icon"></span>
{{item.name}}
</a>
</md-list-item>
</md-list>
I can't seem to get it to work, getting this error upon loading the page:
Error: [$parse:syntax] Syntax Error: Token '{' invalid key at column 2 of the expression [{{item.move}}] starting at [{item.move}}].
http://errors.angularjs.org/1.4.8/$parse/syntax?p0=%7B&p1=invalid%20key&p2=2&p3=%7B%7Bitem.move%7D%7D&p4=%7Bitem.move%7D%7D
at http://localhost:3000/bower_components/angular/angular.js:68:12
at Object.AST.throwError (http://localhost:3000/bower_components/angular/angular.js:13100:11)
at Object.AST.object (http://localhost:3000/bower_components/angular/angular.js:13087:16)
at Object.AST.primary (http://localhost:3000/bower_components/angular/angular.js:12995:22)
at Object.AST.unary (http://localhost:3000/bower_components/angular/angular.js:12983:19)
at Object.AST.multiplicative (http://localhost:3000/bower_components/angular/angular.js:12970:21)
at Object.AST.additive (http://localhost:3000/bower_components/angular/angular.js:12961:21)
at Object.AST.relational (http://localhost:3000/bower_components/angular/angular.js:12952:21)
at Object.AST.equality (http://localhost:3000/bower_components/angular/angular.js:12943:21)
at Object.AST.logicalAND (http://localhost:3000/bower_components/angular/angular.js:12935:21) <a href="{{item.link}}" ng-click="{{item.move}}">
Am I missing something, or is what I'm attempting an illegal action?
You don't need {{}}.
Try:
ng-click='item.move()'
Also your move value is text. It should be a function:
{
label: 'Controls',
icon: 'fa fa-sliders fa-fw 4x',
name: 'Controls',
link: '#/ctrlPage',
move: function() {
console.log("On control page.")
}
},
You should do it like this
ng-click="item.move()"
{{ }} are used for "printing out", so what you did is you inserted value that is returned from item.move() into ng-click=""
I think you need to change your move field from string to function, like
$scope.list = [{
label: 'Controls',
icon: 'fa fa-sliders fa-fw 4x',
name: 'Controls',
link: '#/ctrlPage',
move: function() {
console.log("On control page.");
}
}];
and then, in html use
ng-click="item.move()"
Another thing you could do is create a helper function in the controller:
$scope.executeCode(code) {
eval(code);
}
then in the template pass the function contents to it:
ng-click="executeCode(item.move)"
Note: the eval function isn't the greatest thing to use but this will get the job done given your data.
Here's a plnkr: http://plnkr.co/edit/pVQaBul6E3nO8oWY5vxS?p=preview