Angular 5 Animations - router transition on browser history back - animation

I'm trying to setup a router animation that slides in one direction when the user click on any [routerLink], but when the user triggers a history.back() clicking in a button inside the page or when they click on the browser back button, I want the animation to go on the opposite direction.
This is the solution I got so far.
Main Component Html
<div class="inicio" [#routerTransition]="getState(o)" (#routerTransition.start)="animationStarted($event)" (#routerTransition.done)="animationDone($event)">
<router-outlet #o="outlet"></router-outlet>
</div>
Main Component TS
getState(outlet: RouterOutlet) {
let state: number = this.appRouterState.getState(outlet.activatedRouteData.state);
return state;
}
This is returning state++ when the user goes forward or state-- when the user goes backward
Animation Trigger Setup
return trigger('routerTransition', [
transition('void => *', [
query(':enter, :leave', style({ position: 'fixed', width: '100%', height: "100%" }), { optional: true }),
group([
query(':enter', [style({ transform: 'translateX(-100%)' }), animate('0.5s ease-in-out', style({ transform: 'translateX(0%)' }))], { optional: true }),
query(':leave', [style({ transform: 'translateX(0%)' }), animate('0.5s ease-in-out', style({ transform: 'translateX(100%)' }))], { optional: true })
])
]),
transition(':increment', [
query(':enter, :leave', style({ position: 'fixed', width: '100%', height: "100%" }), { optional: true }),
group([
query(':enter', [style({ transform: 'translateX(-100%)' }), animate('0.5s ease-in-out', style({ transform: 'translateX(0%)' }))], { optional: true }),
query(':leave', [style({ transform: 'translateX(0%)' }), animate('0.5s ease-in-out', style({ transform: 'translateX(100%)' }))], { optional: true })
])
]),
transition(':decrement', [
query(':enter, :leave', style({ position: 'fixed', width: '100%', height: "100%" }), { optional: true }),
group([
query(':enter', [style({ transform: 'translateX(100%)' }), animate('0.5s ease-in-out', style({ transform: 'translateX(0%)' }))], { optional: true }),
query(':leave', [style({ transform: 'translateX(0%)' }), animate('0.5s ease-in-out', style({ transform: 'translateX(-100%)' }))], { optional: true })
])
])
]);
State control service
export interface ItemHistorico {
index: number;
url: string;
}
#Injectable()
export class AppRouterState {
private lastIndex: number = 0;
private isBack: boolean = false;
private historico: ItemHistorico[] = [];
constructor(private router: Router, private menuService: MenuService) { }
public loadRouting(): void {
this.router.events.filter(event => event instanceof NavigationEnd).subscribe(({ urlAfterRedirects }: NavigationEnd) => {
if (urlAfterRedirects !== "/") {
let last: ItemHistorico = _.maxBy(this.historico, h => h.index);
let max: number = last ? last.index : 1;
let next = max + 1;
this.historico = [...this.historico, { index: next, url: urlAfterRedirects }];
if (!this.isBack) {
this.lastIndex++;
}
else {
this.isBack = false;
}
}
else {
this.menuService.obterPaginaInicial().subscribe(menuItem => {
let url = menuItem.url;
this.router.navigate([`/${url}`]);
});
}
});
window.onpopstate = ev => {
let hash: string = (ev.currentTarget as Window).location.hash;
if (hash === "#/") {
this.isBack = false;
}
else {
this.isBack = true;
this.lastIndex--;
}
};
}
public getHistory(): ItemHistorico[] {
return this.historico;
}
public getState(current: string): number {
return this.lastIndex;
}
public getIsBack(): boolean {
return this.isBack;
}
}
Obs.: The "void=>*" transition is working and the ":increment" is also working, the problem lies when the user goes backwards, although the state changes and the component loads without problems the animation don't trigger.
Tks for the help.

I manage to resolve the problem. So for anyone who needs a similar solution here goes:
Main Component Template
<div class="inicio" [#routerTransition]="getState(o)">
<router-outlet #o="outlet"></router-outlet>
</div>
Main Component Class
currentState: number = 0;
lastPage: string;
getState(outlet: RouterOutlet) {
let state: string = outlet.activatedRouteData.state;
if (this.lastState !== state) {
let dir: string = this.appRouterState.getDirection(state);
if (dir === "f") {
this.currentState++;
}
else {
this.currentState--;
}
this.lastPage= state;
}
return this.currentState;
}
History navigation control service
#Injectable()
export class AppRouterState {
private history: string[] = [];
private isBack: boolean;
constructor(private router: Router) { }
public loadRouting(): void {
this.router.events.filter(event => event instanceof NavigationEnd).subscribe(({ urlAfterRedirects }: NavigationEnd) => {
this.history= [...this.history, urlAfterRedirects ];
});
window.onpopstate = ev => {
this.isBack = true;
};
}
public getHistory(): string[] {
return this.history;
}
public getDirection(page: string): string {
if (this.isBack) {
if (`/${page}` === this.history[this.history.length - 3]) {
this.history.splice(this.history.length - 2, 2);
this.isBack = false;
return "b";
}
}
return "f";
}
}
Animation setup
export function routerTransition() {
return trigger('routerTransition', [
transition(':increment', [
query(':enter, :leave', style({ position: 'fixed', width: '100%', height: "100%" }), { optional: true }),
group([
query(':enter', [style({ transform: 'translateX(100%)' }), animate('0.5s ease-in-out', style({ transform: 'translateX(0%)' }))], { optional: true }),
query(':leave', [style({ transform: 'translateX(0%)' }), animate('0.5s ease-in-out', style({ transform: 'translateX(-100%)' }))], { optional: true })
])
]),
transition(':decrement', [
query(':enter, :leave', style({ position: 'fixed', width: '100%', height: "100%" }), { optional: true }),
group([
query(':enter', [style({ transform: 'translateX(-100%)' }), animate('0.5s ease-in-out', style({ transform: 'translateX(0%)' }))], { optional: true }),
query(':leave', [style({ transform: 'translateX(0%)' }), animate('0.5s ease-in-out', style({ transform: 'translateX(100%)' }))], { optional: true })
])
])
]);
}

Just a heads up to those who arrived here. The solution does work as of May 2019. Just a few corrections and reminders to be made.
In Main Component Class, this.lastState should be this.lastPage
In you routes file, make sure to add data { state: 'PATH_NAME' }. The code needs this to cross-check on navigation history saved in the service.
Other than that, as long as you've used the correct syntax and added the animations to your router-outlet wrapper div then you should be good to go!

Related

fabric.js works with subclass

I try to create new class working with fabric.js framework. This class should consist of 3 simple objects: 2 text and 1 rectangle. One of text object should be updated by time, for example each second. The problem is new value does not appear on canvas as expected, but it updates every time when you select object. Here is my code. Could anyone explain me, what should I do to make it updates by time?
var canvas = new fabric.Canvas('c');
fabric.Tag = fabric.util.createClass(fabric.Group, {
type: 'PItag',
initialize: function() {
options = {};
options.top = 0;
options.left = 0;
var defaults = {
width: 100,
height: 40,
originX: 'center',
originY: 'center'
};
var defaults1 = {
width: 100,
height: 20,
originX: 'center',
originY: 'top',
top: -20,
backgroundColor: 'red'
};
var defaults2 = {
width: 100,
height: 20,
originX: 'center',
originY: 'top',
top: 0
};
var items = [];
items[0] = new fabric.Rect($.extend({}, defaults, {
fill: '#77AAFF',
}));
items[1] = new fabric.Textbox('PI tag name', $.extend({}, defaults1, {
textAlign: 'center',
fontSize: 14
}));
items[2] = new fabric.IText('####', $.extend({}, defaults2, {
textAlign: 'center',
fontSize: 16
}));
this.callSuper('initialize', items, options);
},
getTagName: function () {
return this._objects[1].text;
},
setTagName: function (value) {
this._objects[1].text = value;
},
getValue: function () {
return this._objects[2].text;
},
setValue: function (value) {
this._objects[2].text = value;
this.canvas.renderAll();
},
_render: function(ctx) {
this.callSuper('_render', ctx);
}
});
var pi = new fabric.Tag();
pi.setTagName("Unix time");
canvas.add(pi);
setInterval(function() {
pi.setValue(Math.floor((new Date()).getTime() / 1000).toString());
canvas.renderAll();
}, 1000);
var canvas = new fabric.Canvas('c');
fabric.Tag = fabric.util.createClass(fabric.Group, {
type: 'PItag',
initialize: function() {
options = {};
options.left = 100;
options.top=100;
var defaults = {
width: 100,
height: 40,
originX: 'center',
originY: 'center'
};
var defaults1 = {
width: 100,
height: 20,
originX: 'center',
originY: 'top',
top: -20,
backgroundColor: 'red'
};
var defaults2 = {
width: 100,
height: 20,
originX: 'center',
originY: 'top',
top: 0
};
var items = [];
items[0] = new fabric.Rect($.extend({}, defaults, {
fill: '#77AAFF',
}));
items[1] = new fabric.Textbox('PI tag name', $.extend({}, defaults1, {
textAlign: 'center',
fontSize: 14
}));
items[2] = new fabric.IText('####', $.extend({}, defaults2, {
textAlign: 'center',
fontSize: 16
}));
this.callSuper('initialize', items, options);
},
getTagName: function () {
return this._objects[1].text;
},
setTagName: function (value) {
this._objects[1].text = value;
},
getValue: function () {
return this._objects[2].text;
},
setValue: function (value) {
this._objects[2].set({ text: value });
this.canvas.renderAll();
},
_render: function(ctx,noTransform) {
console.log('xs')
this.callSuper('_render', ctx);
//ctx._objects[1].text = this._objects[1].text;
}
});
var pi = new fabric.Tag();
// canvas.pi.async = true;
pi.setTagName("Unix time");
canvas.add(pi);
setInterval(function() {
pi.setValue(Math.floor((new Date()).getTime() / 1000).toString());
canvas.renderAll();
}, 1000);
<script src="http://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.7.9/fabric.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<canvas id="c" height="418" width="400" style="border: 1px solid rgb(170, 170, 170);"></canvas>
just change this function
setValue: function (value) {
this._objects[2].set({ text: value });
this.canvas.renderAll();
},

Animation - How to turn animated values into real values via interpolate

I'm trying to simultaneously restrict the values of my animation (using clamp as well as interpolate) but also get the values out of the interpolation so I can use them. Specifically because I want to update a piece of state with them and create an observable from that. I just can't figure out how to extract the 'real' value out of the AnimatedValue that is produced by the interpolation (in this case state.panValue). I've tried
this.state.panValue.value
and
this.state.panValue._value
and they come back as undefined. If anyone could help me out would be amazing!
EDIT: I'd also be really happy to just have the
this.state.pan.x
variable updated within the limits so I can skip the whole updating the state variable 'panValue' thing. A nice guy on Facebook suggested that I could implement this limit somehow inside the onPanResponderMove by switching the variable to a function or something but I've tried several things and all I get are errors, I guess because I don't really know how to 'safely' amend these animated values.
onPanResponderMove: Animated.event([
null,
{ dx: this.state.pan.x },
]),
Original Code:
import React, { Component } from 'react';
import {
View,
Animated,
PanResponder,
Text,
} from 'react-native';
import styles from './styles';
class ClockInSwitch extends Component {
constructor(props) {
super(props);
this.state = {
pan: new Animated.ValueXY(),
panValue: 0,
};
}
componentWillMount() {
this._animatedValueX = 0;
this._animatedValueY = 0;
this.state.pan.x.addListener((value) => {
this._animatedValueX = value.value;
this.setState({
panValue: this.state.pan.x.interpolate({
inputRange: [-30, 0, 120,],
outputRange: [-10, 0, 120,],
extrapolate: 'clamp',
}),
});
});
this._panResponder = PanResponder.create({
// Ask to be the responder:
onStartShouldSetPanResponder: (evt, gestureState) => true,
onStartShouldSetPanResponderCapture: (evt, gestureState) => true,
onMoveShouldSetPanResponder: (evt, gestureState) => true,
onMoveShouldSetPanResponderCapture: (evt, gestureState) => true,
onPanResponderGrant: (evt, gestureState) => {
this.state.pan.setOffset({
x: this._animatedValueX,
});
this.state.pan.setValue({ x: 0, y: 0 });
},
onPanResponderMove: Animated.event([
null,
{ dx: this.state.pan.x },
]),
onPanResponderTerminationRequest: (evt, gestureState) => true,
onPanResponderRelease: (evt, gestureState) => {
this.state.pan.flattenOffset();
Animated.timing(this.state.pan, {
toValue: 0,
duration: 500,
}).start();
},
onPanResponderTerminate: (evt, gestureState) => {
},
onShouldBlockNativeResponder: (evt, gestureState) => {
return true;
},
});
}
componentWillUnMount() {
this.state.pan.x.removeAllListeners();
}
render() {
const animatedStyle = {
transform: [{
translateX: this.state.panValue,
},
],
};
return (
<View>
<Text>{this.state.pan.x._value}</Text>
<View style={styles.buttonStyle}>
<Animated.View
style={[styles.sliderButtonStyle, animatedStyle]}
{...this._panResponder.panHandlers}
/>
</View>
</View>
);
}
}
export default ClockInSwitch;
I think this is what you're looking for. I'm using exponent so your declaration for vector icons would probably need to be changed. Cheers!
/**
* #providesModule ClockInSwitch
* #flow
*/
import React, {Component} from 'react';
import {View, Animated, StyleSheet, PanResponder, Text} from 'react-native';
import {FontAwesome} from '#exponent/vector-icons';
export class ClockInSwitch extends Component {
constructor(props) {
super(props);
this.state = {
pan: new Animated.ValueXY(),
panValue: 0
};
}
componentWillMount() {
this._panResponder = PanResponder.create({
onMoveShouldSetResponderCapture: () => true,
onMoveShouldSetPanResponderCapture: () => true,
onPanResponderGrant: (e, gestureState) => {
this
.state
.pan
.setValue({x: 0, y: 0});
},
//here's where you can check, constrain and store values
onPanResponderMove: (evt, gestureState) => {
// 300 is the width of the red container (will leave it to you to calculate this
// dynamically) 100 is the width of the button (90) plus the 5px margin on
// either side of it (10px total)
var newXVal = (gestureState.dx < 300 - 100)
? gestureState.dx
: 300 - 100;
this
.state
.pan
.x
.setValue(newXVal);
//set this state for display
this.setState({panValue: newXVal});
},
onPanResponderRelease: (e, {vx, vy}) => {
this
.state
.pan
.flattenOffset();
Animated
.spring(this.state.pan, {
toValue: 0,
duration: 400,
overshootClamping: true
})
.start();
this.setState({panValue: 0});
}
});
}
componentWillUnMount() {
this
.state
.pan
.x
.removeAllListeners();
}
render() {
//decouple the value from the state object
let {pan} = this.state;
let [translateX,
translateY] = [pan.x, pan.y];
let translateStyle = {
transform: [{
translateX
}, {
translateY
}]
};
return (
<View>
<Text style={styles.leftText}>Power Button Demo</Text>
<View style={styles.buttonStyle}>
<Animated.View
style={[styles.sliderButtonStyle, translateStyle]}
{...this._panResponder.panHandlers}>
<FontAwesome
name="power-off"
color="#EA2E49"
style={{
alignSelf: "center",
marginHorizontal: 10
}}
size={36}/>
</Animated.View>
</View>
<Text style={styles.rightText}>{this.state.panValue}: x value</Text>
</View>
);
}
}
export default ClockInSwitch;
const styles = StyleSheet.create({
sliderButtonStyle: {
borderColor: '#FCFFF5',
borderStyle: 'solid',
borderWidth: .5,
backgroundColor: '#FCFFF5',
borderRadius: 45,
height: 90,
width: 90,
justifyContent: 'center',
textAlign: 'center',
marginHorizontal: 5,
shadowColor: '#333745',
shadowOffset: {
width: 2,
height: 2
},
shadowOpacity: .6,
shadowRadius: 5
},
buttonStyle: {
borderColor: '#FCFFF500',
backgroundColor: '#DAEDE255',
borderStyle: 'solid',
borderWidth: 1,
height: 100,
width: 300,
justifyContent: 'center',
borderRadius: 50,
margin: 5,
flexDirection: 'column'
},
rightText: {
justifyContent: 'center',
textAlign: 'right',
fontWeight: '100',
marginHorizontal:15,
fontSize: 20,
color: '#FCFFF5',
marginVertical:25,
flexDirection: 'column'
},
leftText: {
justifyContent: 'center',
textAlign: 'left',
fontWeight: '100',
marginHorizontal:15,
fontSize: 24,
color: '#FCFFF5',
marginVertical:25,
flexDirection: 'column'
}
});

IE8 Invalid Argument

I am working on some existing code. After upgrading to Extjs 4, one of our application view window is broken. It is working fine on Firefox, not IE8. Upon the popup window opening, I am getting Invalid argument, and the debugger indicates it is on like Sytle[hook.name] = value;
I've tried to remove the height (which I really need) after reading some posts, but it is still not working. Please advise.
Thanks.
Ext.define(view.window.popupwindow', {
extend : 'Ext.Window',
alias : 'widget.popupwindow',
requires: [view.grid.issuerpopupgrid'],
appContainer: undefined,
caller: undefined,
selReportType:undefined,
reloadData: true,
extraParam: undefined,
initComponent: function() {
var config = {
width: 750,
minWidth: 600,
minHeight: 300,
autoScroll: false,
modal: true,
border: false,
closable: true,
constrain: false,
resizable: true,
maximizable: true,
layout:'anchor',
items: this.buildWindow(),
listeners: {
scope: this,
show: function(form) {
//sync the shadow
var win = Ext.WindowMgr.getActive();
if (win!=null) win.el.sync(true);
}
}
};
Ext.apply(this, config);
this.callParent(arguments);
},
buildWindow: function() {
return [{
xtype: 'issuerpopupgrid',
id:'issuerpopupgrid-id',
appContainer: this.appContainer,
extraParam: this.extraParam
}];
},
});
Ext.define('view.grid.issuerpopupgrid', {
extend : 'view.grid.lvsimplegrid',
alias : 'widget.issuerpopupgrid',
appContainer: undefined,
extraParam: undefined,
initComponent: function() {
this.gridType = this.appContainer.appContext.appData.gridDefTypeMap.R9;
this.modelName = this.appContainer.name+'.model.'+this.gridType.name;
this.selReportType = this.gridType.name; //'R9';
this.sortField = 'secDesc';
this.reportUrl = this.appContainer.appContext.appData["gridDefinitions"][this.gridType.name].serviceUrl;
var config = {
height: 570,
selModel: {
selType: 'checkboxmodel',
showHeaderCheckbox :true,
mode: 'MULTI',
checkOnly: true
},
listeners: {
scope: this,
afterrender: this.onAfterRender,
show: this.onActivateGrid
}
};
Ext.apply(this, config);
this.callParent(arguments);
this.tbar = this.buildTopBar();
},
onAfterRender: function(thisObj) {
this.configureGrid(this.selReportType, this.appContainer.appContext.appData, null, false, this.sortField, this.sortField);
thisObj.getStoreData(this.selReportType, this.extraParam);
},
onActivateGrid: function(thisObj) {
thisObj.getStoreData(this.selReportType);
}
});
Looks like you've got a trailing comma:
buildWindow: function() {
return [{
xtype: 'issuerpopupgrid',
id:'issuerpopupgrid-id',
appContainer: this.appContainer,
extraParam: this.extraParam
}];
}, //<-- trailing comma
IE will have issues with this... You can use jsHint to find syntax errors like this: https://jslinterrors.com/extra-comma
This is the fully linted code:
Ext.application({
name : 'Fiddle',
launch : function () {
Ext.define('view.window.popupwindow', {
extend : 'Ext.Window',
alias : 'widget.popupwindow',
requires: ['view.grid.issuerpopupgrid'],
appContainer: undefined,
caller: undefined,
selReportType: undefined,
reloadData: true,
extraParam: undefined,
initComponent: function () {
var config = {
width: 750,
minWidth: 600,
minHeight: 300,
autoScroll: false,
modal: true,
border: false,
closable: true,
constrain: false,
resizable: true,
maximizable: true,
layout: 'anchor',
items: this.buildWindow(),
listeners: {
scope: this,
show: function () {
//sync the shadow
var win = Ext.WindowMgr.getActive();
if (win !== null) {
win.el.sync(true);
}
}
}
};
Ext.apply(this, config);
this.callParent(arguments);
},
buildWindow: function () {
return [{
xtype: 'issuerpopupgrid',
id: 'issuerpopupgrid-id',
appContainer: this.appContainer,
extraParam: this.extraParam
}];
}
});
Ext.define('view.grid.issuerpopupgrid', {
extend : 'view.grid.lvsimplegrid',
alias : 'widget.issuerpopupgrid',
appContainer: undefined,
extraParam: undefined,
initComponent: function () {
this.gridType = this.appContainer.appContext.appData.gridDefTypeMap.R9;
this.modelName = this.appContainer.name + '.model.' + this.gridType.name;
this.selReportType = this.gridType.name; //'R9';
this.sortField = 'secDesc';
this.reportUrl = this.appContainer.appContext.appData.gridDefinitions[this.gridType.name].serviceUrl;
var config = {
height: 570,
selModel: {
selType: 'checkboxmodel',
showHeaderCheckbox : true,
mode: 'MULTI',
checkOnly: true
},
listeners: {
scope: this,
afterrender: this.onAfterRender,
show: this.onActivateGrid
}
};
Ext.apply(this, config);
this.callParent(arguments);
this.tbar = this.buildTopBar();
},
onAfterRender: function (thisObj) {
this.configureGrid(this.selReportType, this.appContainer.appContext.appData, null, false, this.sortField, this.sortField);
thisObj.getStoreData(this.selReportType, this.extraParam);
},
onActivateGrid: function (thisObj) {
thisObj.getStoreData(this.selReportType);
}
});
}
});

How can I put a image on center of titlebar in Sencha Touch 2?

I need to put a image on center of titlebar in sencha touch 2 , but I can't! I touch js and CSS but it's impossible.... any idea, please? Thanks!
try this one it will help for You..
Its very simple...
title:'give image tag with location thats all'
You can try setTitle('<div class="logo"/>')
and
.logo {
background: url('../images/logo.png') no-repeat center;
width:100px;
height:40px
}
ImageTitleBar class.
Ext.define('myapp.controls.ImageTitleBar', {
extend: 'Ext.TitleBar',
alias: 'widget.imageTitleBar',
requires: [
'Ext.Img'
],
config: {
imageSource: ''
},
applyInitialItems: function(items) {
var me = this,
defaults = me.getDefaults() || {};
me.initialItems = items;
me.leftBox = me.add({
xtype: 'container',
style: 'position: relative',
layout: {
type: 'hbox',
align: 'center'
},
listeners: {
resize: 'refreshTitlePosition',
scope: me
}
});
me.spacer = me.add({
xtype: 'component',
style: 'position: relative',
flex: 1,
listeners: {
resize: 'refreshTitlePosition',
scope: me
}
});
me.rightBox = me.add({
xtype: 'container',
style: 'position: relative',
layout: {
type: 'hbox',
align: 'center'
},
listeners: {
resize: 'refreshTitlePosition',
scope: me
}
});
me.titleComponent = me.add({
xtype: 'container',
hidden: defaults.hidden,
centered: true,
layout: {
type: 'hbox',
align: 'middle'
}
});
me.titleImage = me.titleComponent.add({
xtype: 'img',
width: 36,
height: 36
})
me.titleLabel = me.titleComponent.add({
xtype: 'title'
});
me.doAdd = me.doBoxAdd;
me.remove = me.doBoxRemove;
me.doInsert = me.doBoxInsert;
},
updateTitle: function(newTitle) {
this.titleLabel.setTitle(newTitle);
this.titleLabel.setHidden(!newTitle);
if (this.isPainted()) {
this.refreshTitlePosition();
}
},
updateImageSource: function(newImageSource) {
this.titleImage.setSrc(newImageSource);
this.titleImage.setHidden(!newImageSource);
if (this.isPainted()) {
this.refreshTitlePosition();
}
}
})

Set Triggerfield value from controller

I try to binding data from window grid that show by trigger field click.
this is my form with triggerfield :
Ext.define('ResApp.view.group.Detail', {
extend: 'Ext.window.Window',
alias:'widget.groupdetail',
floating: true,
hidden: false,
width: 450,
//height: 400,
resizeable: false,
title: 'Detail Group',
modal: true,
initComponent: function() {
var me = this;
Ext.applyIf(me, {
....other config...
items: [
{
xtype: 'form',
itemId: 'groupDetailForm',
border: false,
layout: {
type: 'auto'
},
bodyPadding: 10,
preventHeader: true,
title: 'My Form',
items: [
....other items...
{
xtype: 'triggerfield',
padding: '0 0 5 0',
width: 350,
fieldLabel: 'Nama Kontak',
name: 'namaJamaah',
itemId: 'namaLead',
triggerCls: ' x-form-search-trigger',
onTriggerClick: function(){
Ext.widget('listjamaahgroup').show();
}
},
....other items...
]
}
]
});
me.callParent(arguments);
}});
next, my window with grid to list data :
Ext.define('ResApp.view.group.ListJamaahGroup', {
extend: 'Ext.window.Window',
alias:'widget.listjamaahgroup',
height: 400,
width: 750,
title: 'Daftar Jamaah',
modal: true,
hidden: false,
floating: true,
resizeable: false,
initComponent: function() {
var me = this;
Ext.applyIf(me, {
items : [
{
xtype: 'gridpanel',
autoScroll: true,
border:false,
title: 'Daftar Anggota',
itemId: 'gridAnggota',
preventHeader: true,
forceFit: true,
flex: 1,
store: 'Jamaah',
allowDeselect : true,
viewConfig: {
autoScroll: true
},
dockedItems: [
{
xtype: 'toolbar',
dock: 'top',
cls:'border-bottom',
items: [
{
xtype: 'button',
text: 'Pilih',
iconCls:'edit',
action: 'selectJamaahGrp',
itemId: 'selectJamaahGrp'
},
{
xtype: 'button',
text: 'Baru',
iconCls:'add'
}
]
}
],
columns: [
....Grid columns...
]
}
]
});
me.callParent(arguments);
}});
and this is my controller :
Ext.define('ResApp.controller.GroupDetails', {
extend: 'Ext.app.Controller',
stores: [
'Group', 'Jamaah'
],
models: [
'Group', 'Jamaah'
],
views:[
'group.Detail',
'group.ListJamaahGroup'
],
init: function(){
this.control({
...
'button[action=selectJamaahGrp]': {
click: this.selectJamaahGrp
},
...
});
},
... other functions ...
selectJamaahGrp: function(button, e, options) {
//windowDetail.hide();
var grid = button.up('grid');
if (grid) {
var windowDetail = Ext.widget('groupdetail');
var form = windowDetail.down('form');
var sm = grid.getSelectionModel();
var rs = sm.getSelection();
if (!rs.length) {
Ext.Msg.alert('Info', 'Pilih salah satu');
return;
}
var data = grid.getSelectionModel().getSelection()[0];
//how to setValue to triggerfield from here
}
button.up('listjamaahgroup').destroy();
},
batalSelClick: function(button, e, options) {
button.up('listjamaahgroup').destroy();
}
... other functions ...})
my problem is, i can't figure how to setValue the triggerfield from my controller. Or there's another way to do it?
Just define a ref in your controller (refs: [ { ref: 'trigger', selector: 'triggerfield' } ]) and then perform this.getTrigger().setValue().

Resources