ion-slides on ionic4 select slide on click - ionic4

I'm using ion-slides to have a slider with different "selectable" tags like the image below
I have already accomplished that. The point that I'm struggling with is that I need to make the slide that I click on selected and the older one unselected without the need to scroll to that slide like the following screenshot
I could get the clicked index dynamically by the following snippet
I register for click action
(ionSlideTouchEnd)="onSlideTap($event)"
Then later on code I get the event
onSlideTap(event) {
this.slides.getSwiper().then(swiper => {
console.log("clicked Index = ", swiper.clickedIndex);
});
}
Does anyone have an idea of how to change active slide without scroll?

I have an idea. I hope it's helpful for you.
Template
<ion-slides #slides (ionSlideTouchEnd)=ionSlideTouchEnd($event)>
<ion-slide class="slide-item" *ngFor="let item of items; index as index;" (click)="onClickSlide(index)">
<ion-button [ngClass]="{'active': activeIndex === index}">{{item.title}}</ion-button>
</ion-slide>
</ion-slides>
TS file
import { IonSlides } from '#ionic/angular';
...
#ViewChild('slides', { read: IonSlides }) slides: IonSlides;
activeIndex: number = 0;
items = [
{
id: 1,
title: 'Item 1'
},
{
id: 2,
title: 'Item 2'
},
{
id: 3,
title: 'Item 3'
}
];
...
onClickSlide(id) {
this.activeIndex = id;
}
// Emitted when the user releases the touch.
ionSlideTouchEnd(){
// Lock the ability to slide to the next or previous slide.
this.slides.lockSwipes(true);
}
Style file
.active {
// style to detect the active slide
}

Related

QML - change how transition between pages looks

I know this is probably super basic, but I am new to learning QML and have a question about transition between pages.
In this example I have a button with which I want to switch between my 3 pages.
the transition works, but the pages always move from the right-to-the-left-side of the window.
how can I change this? I need the new page to appear as a whole right away.
(e.g. when changing from firstPage to secondPage, for the user it looks like only the AppText changes, because the button is at the same position in both cases)
code example:
App {
id: app
width: px(250); height: px(250)
NavigationStack {
Page {
id: page
navigationBarHidden: true
AppText { text: "startpage" }
SimpleButton{
x: 220; y: 0
onClicked: page.navigationStack.push(firstPage)
}
}
}
Component {
id: firstPage
Page {
navigationBarHidden: true
AppText { text: qsTr("1st page") }
SimpleButton{
x: 220; y: 0
onClicked: page.navigationStack.push(secondPage)
}
}
}
Component {
id: secondPage
Page {
navigationBarHidden: true
AppText { text: qsTr("2nd page") }
SimpleButton{
x: 220; y: 0
onClicked: page.navigationStack.push(page)
}
}
}
}
Any help would be greatly appreciated!
It looks like you're using Felgo, which I think is an extra library on top of Qt. For instance, there is no built-in QML component called NavigationStack. That comes from Felgo. You should mention that in your question to get better help with it.
I've never used Felgo myself, but just looking at the documentation real quick, it looks like you need to define a new transitionDelegate for your needs. Here is the example they give where new pages fade in/fade out.
NavigationStack {
// custom transition delegate
transitionDelegate: StackViewDelegate {
pushTransition: StackViewTransition {
NumberAnimation {
target: enterItem
property: "opacity"
from: 0
to: 1
duration: 1000
}
}
popTransition: StackViewTransition {
NumberAnimation {
target: exitItem
property: "opacity"
from: 1
to: 0
duration: 1000
}
}
}
initialPage: pageComponent
}

ag-grid: how to add button in master detail template

I am using master/detail in ag-grid. I want a save button in detailed section after all rows. I am able to do that using template, but its not firing the event. I think its just a template and don't work for event. Can you please suggest me how can I add button in detailed section
here is my code
columnDefs: [
{
headerName: "CompanyName",
field: "CompanyName",
cellRenderer: "agGroupCellRenderer"
}
],
groupDefaultExpanded: 0,
detailRowHeight: 200,
detailCellRendererParams: {
detailGridOptions: {
columnDefs: [
{
headerName: "Name",
field: "Name",
cellRenderer: "agGroupCellRenderer"
},
{
headerName: "Age",
field: "Age",
suppressFilter: true,
},
{
headerName: "Gender",
field: "Gender",
suppressFilter: true,
}
],
onGridReady: function (params: any) {
params.api.sizeColumnsToFit();
}
},
getDetailRowData: function (params: any) {
params.successCallback(params.data.ChannelComponentsVm);
},
template:
'<div style="height: 100%;">' +
'<div ref="eDetailGrid" style="height: 90%;"></div>' +
'<div style="height: 10%;"> <button (click)="saveEmployeeDetails()">Save</button> </div>' +
'</div>'
}
I cannot use it in cell renderer as the button is not in column. It should be at the end of the child grid.
-> parent row
-> child row1
-> child row2
-> child row3
Save button
How to add save button at the end of detailed rows
// get ag grid template ref
#ViewChild('agGrid') agGrid: TemplateRef < any > ;
// attach the click listener on row group opened grid event.
// don't forget to clean up this listener on destroy component event or somewhere in the code
rowGroupOpened(params: any) {
var saveButton = this.agGrid["_nativeElement"].querySelector(`#saveDetailsButton`);
if (saveButton) {
saveButton.addEventListener('click',this.saveEmployeeDetails.bind(this));
}
}
saveEmployeeDetails(): void {
console.log('save button clicked');
}
vinoth's answer has the right idea, but I wanted to give a more complete answer shown a slightly different way. To start with, I had the same issue with the event not firing - this is due to lifecycle events and how things are compiled. If you are using a template (as shown in the question) then you cannot put the onClick event in the HTML in the template, you have to instead do it in TypeScript/JavaScript in the .ts file.
In your HTML where you define the ag-grid div, assign the action method rowGroupOpened. This should be in your HTML file, or possibly in your .ts file (not in the template in grid definitions).
(rowGroupOpened)="rowGroupOpened($event)"
In your .ts file, define the rowGroupOpened event.
RowGroupOpened(params: any) {
//below pass the id of your button/div used in your template
const buttonDiv = document.getElementById('saveButton');
if (buttonDiv){
buttonDiv.addEventListener('click', (e) => {
this.myButtonClickMethod();
});
}
}
myButtonClickMethod() {
//do something
}
Your button in the template string should have an id like this:
<button id="saveButton">Save</button>
This way when one of your detail grids expanded it will attach the onClick method at that time. Remember that by default, if a detail grid is not expanded then it doesn't exist/is undefined. Also don't forget to do cleanup/destroy when needed.

blackberry 10 global tab bar application(global TabbedPane)

I am creating a application which has a global tab bar ."Actionbar" should have 5 buttons and should be seen on every screen.
Is there any way to place 5 tabs on "ActionBar" at one moment without help of "tabbed menu" ?
And how I can make this tabbed-pane global? because latter in the app I use navigationPane and it replaces tabbedpane. I want the tabbedPane bar to be visible on all screens
UPDATE ::::
I tried sheets but tabs are dissappearing
import bb.cascades 1.0
TabbedPane {
showTabsOnActionBar: true
Tab {
Page {
titleBar: TitleBar {
title: "1"
}
attachedObjects: [
ComponentDefinition {
id: mySheet
source: "sheets.qml"
}
]
Button {
onClicked: {
var sheet = mySheet.createObject();
sheet.open();
}
text: "sheet"
}
}
}
Tab {
}
}
and my sheets.qml file
import bb.cascades 1.0
Sheet {
id: mySheet
content: Page {
Container {
Label {
text: "Hi then"
}
Button {
text: "close"
onClicked: {
onClicked: mySheet.close()
}
}
}
}
}
"And how I can make this tabbedpane global? because latter in the app I use navigationPane and it replaces tabbedpane."
If I understand your question correctly, you want there to always be a tabbedpane instead of it being replaced by the navigationpane later.
What you need to to is have your tabbedpane as the main object in your qml. The navigationpane should be inside each tab, so basically 5 tabs means you would have 5 x navigation panes.
When you need to push a page, push it to the relevant tab's navigationpane.
UPDATE:
Sheets allow you to push a page ontop of the tabbedpane. Here is an example:
Create a qml file with the root item being a sheet, e.g.
Sheet {
content: Page {
Container {
... insert content
}
}
}
Then in your tabbedpane you would do the following:
inside attachedObjects
ComponentDefinition {
id: sheetDefinition
source: "mypage.qml"
}
in your function/onclick/etc:
var sheet = sheetDefinition.createObject;
sheet.open();
UPDATE 2:
To push pages within a tabbedpane do something similar to the following:
TabbedPane {
Tab {
NavigationPane {
id: tab1Nav
Page {
}
}
}
}
Then to push a page use
tab1Nav.push(page);
Or replace the content of the navigationpane to keep the tabs in place.

One view and multiple controller actions for the same button in EXTJS

Am having a delete button in my EXTJS Application. On clicking the button, am opening a confirmation form, asking the user are they sure to delete the item. The delete button is a part of many forms in my Application. And irrespective of the form being used, am opening the confirmation window.
And on clicking the yes button in the confirmation window, i want to do some action. But these actions have to be specific to the form that was opened first.So, am confused about how to use the same view, the same button, but different actions depending upon the first form that was opened.
View: This is the window that opens on clicking the delete button in any of the forms
Ext.define('app.view.GenMessageWin', {
extend : 'Ext.panel.Panel',
alias : 'widget.genmessagewin',
var fp = {
xtype : 'panel',
itemId : 'MSGPANEL',
width : Width,
height : 150,
cls : 'msg effect1',
layout : 'form',
border : false,
items : [{
xtype : 'panel',
//cls : 'winTitle',
html : msgTxt,
border : 0
}, {
xtype : 'form',
itemId : 'MSGFORM',
border : false,
title : '',
buttonAlign : 'center',
fieldDefaults : {
msgTarget : 'side',
labelWidth : 110,
size : 30
},
buttons : [{
text : LANG.BTYES,
iconCls : 'icon-tick-tb',
iconAlign : 'right',
cls : 'tip-btn',
action : 'delete',
id : 'BTYES'
}, {
text : LANG.BTNO,
iconCls : 'icon-cross-tb',
iconAlign : 'right',
cls : 'tip-btn',
action : 'notDelete',
id : 'BTNO'
} ]
Controller
init : function() {
this.control({
'button[action = delete]' : {
click : this.delete
},
'button[action = notDelete]' : {
click : this.notDelete
},
So, in the delete action, we have to determine which form has been opened in the first place, and then delete the data accordingly.
You have 3 options:
1) Make the selector more specific:
'form1 button[action=delete]': {
click: this.form1Delete
},
form1Delete: function(){
this.showMsg(function() {
// form 1 delete
});
}
2) Traverse back up the component hierarchy and find the open form
onDelete: function(btn) {
var form = btn.up('form'); // find an xtype form or subclass
if (form.someCondition) {
//foo
} else {
//bar
}
}
3) As suggested by Dmitry. You'll need to convert it over to 'MVC style'.
Ext.define('ConfirmButton', {
extend: 'Ext.button.Button',
title: '',
msg: '',
requires: ['Ext.window.MessageBox'],
initComponent: function(){
this.callParent();
this.on('click', this.handleClick, this);
},
handleClick: function(){
Ext.MessageBox.confirm(this.title, this.msg, this.checkResponse, this);
},
checkResponse: function(btn){
if (btn == 'yes') {
this.fireEvent('confirm', this);
}
}
});
Ext.onReady(function(){
var btn = new ConfirmButton({
renderTo: document.body,
text: 'Foo',
title: 'Should I',
msg: 'Are you sure'
});
btn.on('confirm', function(){
console.log('Do something');
})
});
I am doing something similar; I simply use the native Ext.Msg class
Controller code
,onDelete: function() {
var me = this;
Ext.Msg.show({
title:'Really shure?',
msg: 'Really wanna do this?',
buttons: Ext.Msg.YESNO,
icon: Ext.Msg.QUESTION,
closable: false,
fn: function(btn) {
if (btn == 'yes') {
me.deleteRecord();
}
},
scope: me
});
}
,deleteRecord: function() {
var me = this,
store = Ext.StoreMgr.lookup('datastore');
store.remove(me.selectedRecord);
store.sync();
}
I would recommend you to keep all logic concerning this within the controller. I your case it'seems that's no problem, cause you just catching the button-events. You problem may be that all controllers catch these, if you are using totally the same window.
You can solve this for example by creating the action property value dynamically when creating the window. Like action='onDeleteCar'
I think you should embed the 'confirmation' functionality inside the button, i.e. create your own ConfirmButton class that would first fire a dialog upon pressing and executing the passed handler only if the dialog exited with "yes".
Here is the example implementation:
Ext.define('My.ConfirmButton', {
extend: 'Ext.button.Button',
alias: 'widget.confirmbutton',
dlgConf: {
title: 'Are you sure?',
msg: 'Are you sure you want to delete this?',
buttons: Ext.Msg.YESNO,
closable: false
},
initComponent: function() {
this.callParent(arguments);
// remember the originally passed handler
this.origHandler = this.handler;
this.origScrope = this.scope;
// override current handler to fire confirmation box first
this.handler = this.confirmHandler;
this.scope = this;
},
confirmHandler: function(me, e) {
// show dialog and call the original handler only on 'yes'
Ext.Msg.show(Ext.applyIf({
fn: function(buttonId) {
if(buttonId == 'yes') {
me.origHandler && me.origHandler.call(me.origScope || me, me, e)
}
},
scope: me
}, this.dlgConf))
},
// Method used to dynamically reassign button handler
setHandler: function(handler, scope) {
// remember the originally passed handler
this.origHandler = this.handler;
this.origScrope = this.scope;
// override current handler to fire confirmation box first
this.handler = this.confirmHandler;
this.scope = this;
return this;
},
});
Here is the sample usage:
Ext.create('My.ConfirmButton', {
text: 'Delete me',
renderTo: Ext.getBody(),
handler: function() {
alert('Aww, you deleted something! :(')
}
});
As you see, the confirmation logic is hidden from the outside world, you use this button exactly like you would use a regular Ext.Button (by passing a handler to it). Also, you can override the configuration of the dialog that the button fires (you may want to adjust it to your needs, e.g. allow passing record name to the dialog for a friendlier UI).
Note that the code isn't thoroughly tested, some cases might be left uncovered.
UPD. You need to add an alias (former xtype) to the component class definition so you can use it in ComponentQuery in your controller code, e.g.
this.control({
'confirmbutton[action = delete]' : {
click : this.delete
},
'confirmbutton[action = notDelete]' : {
click : this.notDelete
}
})
The final solution that i used was to declare variables using the global namespace so that they can be accessed from anywhere. On opening the first form, i get the data from the form using the record variable, and assign them a global name like
App1.Var1 = record.data.id;
And, on opening the delete window, these variables can be accessed by App1.Var1 when the buttons are clicked.

Adding a button and navigating between views

1.) I need to add 2 buttons, one below another. My working so far is demonstrated below; It only shows one button, but how can i add another button with a different button image below this button ?
2.) When the user clicks a button, i need to navigate to another screen. How can i do this ?
I need the equivalent of the following objective-c code ?
View1 *view1 = [[View1 alloc] initWithNibName:#"View1" bundle:nil];
[self.navigationController pushViewController:View1 animated:YES];
3.) How can i add a navigation Bar (equivalent to the navigation bar shown in iPhone)
The code for the 1st question;
{
items:[
{
xtype:'button',
text: 'Submit',
ui:'confirm',
handler: function(){
var values = Ext.getCmp('contactForm').getValues();
Ext.Ajax.request({
url: 'http://loonghd.com/service/',
failure: function (response) {
//do something
}, success: function (response) {
// do something
}
});
}
}
]
}
1) For getting two buttons one below the other, you can add two separate buttons (with different ui property) as childs of a form panel. I think, this is what you need.
Just like this,
....
....
items : [
{
xtype:'button',
text: 'Submit',
ui:'confirm', // makes the button color as green
handler: function(){
var values = Ext.getCmp('contactForm').getValues();
Ext.Ajax.request({
url: 'http://loonghd.com/service/',
failure: function (response) {
//do something
},
success: function (response) {
// do something
}
});
}
},
{
xtype:'button',
text:'Second button',
ui:'decline', // makes the button color as red.
listeners : {
tap : function() {
Ext.Msg.alert('You just clicked Second button');
}
}
}
]
....
....
2) 3) For your 2nd and 3rd question, navigationview is the solution.
Solution posted by M-x is great, but it's very advanced level example & also difficult to understand at first instance.
Here's an easy solution of navigatioview from Sencha Docs.
//create the navigation view and add it into the Ext.Viewport
var view = Ext.Viewport.add({
xtype: 'navigationview',
//we only give it one item by default, which will be the only item in the 'stack' when it loads
items: [
{
//items can have titles
title: 'Navigation View',
padding: 10,
//inside this first item we are going to add a button
items: [
{
xtype: 'button',
text: 'Push another view!',
handler: function() {
//when someone taps this button, it will push another view into stack
view.push({
//this one also has a title
title: 'Second View',
padding: 10,
//once again, this view has one button
items: [
{
xtype: 'button',
text: 'Pop this view!',
handler: function() {
//and when you press this button, it will pop the current view (this) out of the stack
view.pop();
}
}
]
});
}
}
]
}
]
});
Maybe a navigation view will work for you? It's the same idea but it's like starting with a UITableView:
http://docs.sencha.com/touch/2-0/#!/example/navigation-view
In the app/controller/Application.js, when you tap on a contact, the detail view gets pushed. All the source is in the examples directory.
onContactSelect: function(list, index, node, record) {
var editButton = this.getEditButton();
if (!this.showContact) {
this.showContact = Ext.create('AddressBook.view.contact.Show');
}
// Bind the record onto the show contact view
this.showContact.setRecord(record);
// Push the show contact view into the navigation view
this.getMain().push(this.showContact);
},