How can I pass arguments to a Sencha 2 template? Below is my small template, have tried different things like defining "field variables" on the template and using the config, and so fourth, but Im definitly doing something wrong. Lets say I want to give arguments "title" and "usageTime", how can I do it
Ext.define('Sencha.templates.AppDetailsUsageTemplate' ,{
extend: 'Ext.XTemplate',
constructor: function (config) {
var html = [
'<div id="{id}" class="limitsList {cls}">',
' <div class="reportsSummaryLeft"> {title} </div>',
' <div class="reportsSummaryRight"> {usageTime} </div>',
' <div style="clear:both"></div>',
'</div>'];
this.callParent(html);
}
});
In my view I wanna do something ala this (pseudo code below):
xtype: 'container',
tpl: Ext.create('Sencha.templates.AppDetailsUsageTemplate',{
title: 'test tittle',
usageTime: 100384
})
I figured it out, give parameters through data:
Examples:
{
id: 'appDetailsMonth',
xtype: 'component',
tpl: Ext.create('Sencha.templates.AppDetailsUsageTemplate')
},{
id: 'appDetailsLifeDuration',
xtype: 'component',
tpl: Ext.create('Sencha.templates.AppDetailsUsageTemplate')
}
And then in applyItems
applyItems:function(newItems, oldItems) {
var i = 0,
iNum = newItems.length,
data = this.getData();
var yesterdayItem = newItems[2];
yesterdayItem.data = {
title: 'Yesterday',
usage: data.dayDuration
};
....
}
Related
I am using Bootstrap Vue to render a select input. Everything is working great - I'm able to get the value and change the UI based on the option that was selected.
I am trying to change the headline text on my page - to be the text of the selected option. I am using an array of objects to render the options in my select input.
Here is what I'm using for my template:
<b-form-group
id="mySelect"
description="Make a choice."
label="Choose an option"
label-for="mySelect">
<b-form-select id="mySelect"
#change="handleChange($event)"
v-model="form.option"
:options="options"/>
</b-form-group>
Here is what my data/options look like that I'm passing to the template:
...
data: () => ({
form: {
option: '',
}
options: [
{text: 'Select', value: null},
{
text: 'Option One',
value: 'optionOne',
foo: {...}
},
{
text: 'Option Two',
value: 'optionTwo',
foo: {...}
},
}),
methods: {
handleChange: (event) => {
console.log('handleChange called');
console.log('event: ', event); // optionOne or optionTwo
},
},
...
I can get optionOne or optionTwo, what I'd like to get is Option One or Option Two (the text value) instead of the value value. Is there a way to do that without creating an additional array or something to map the selected option? I've also tried binding to the actual options object, but haven't had much luck yet that route either. Thank you for any suggestions!
Solution
Thanks to #Vuco, here's what I ended up with. Bootstrap Vue passes all of the select options in via :options. I was struggling to see how to access the complete object that was selected; not just the value.
Template:
<h1>{{ selectedOption }}</h1>
<b-form-group
id="mySelect"
description="Make a choice."
label="Choose an option"
label-for="mySelect">
<b-form-select id="mySelect"
v-model="form.option"
:options="options"/>
</b-form-group>
JS:
...
computed: {
selectedOption: function() {
const report = this.options.find(option => option.value === this.form.option);
return option.text; // Option One
},
methods: {
//
}
...
Now, when I select something the text value shows on my template.
I don't know Vue bootstrap select and its events and logic, but you can create a simple computed property that returns the info by the current form.option value :
let app = new Vue({
el: "#app",
data: {
form: {
option: null,
},
options: [{
text: 'Select',
value: null
},
{
text: 'Option One',
value: 'optionOne'
},
{
text: 'Option Two',
value: 'optionTwo'
}
]
},
computed: {
currentValue() {
return this.options.find(option => option.value === this.form.option)
}
}
});
<div id="app">
<b-form-group id="mySelect" description="Make a choice." label="Choose an option" label-for="mySelect">
<b-form-select id="mySelect" v-model="form.option" :options="options" />
</b-form-group>
<p>{{ currentValue.text }}</p>
</div>
Here's a working fiddle.
You have an error in your dictionary.
Text is showed as an option.
Value is what receive your variable when option is selected.
Is unneccesary to use computed property in this case.
let app = new Vue({
el: "#app",
data: {
form: {
option: null,
},
options: [{
value: null,
text: 'Select'
},
{
value: 'Option One',
text: 'Option One'
},
{
value: 'Option Two',
text: 'Option Two'
}
]
}
});
Fiddle with corrections
Documentation
I am creating an application using Quasar and VueJS. I am able to generate a dynamic form on click of the add button, but not able to delete any of the newly generated form based on the click of the delete button.Find the code below:
<template>
<div v-for="h in htmlList">
<div v-for="r in h" >
<div v-html="r" v-on:click="useRemoveFromProject(1)" v-bind:id="r.id">
</div>
</div>
</div>
</template>
<script>
/*
* Root component
*/
import Vue from 'vue'
export default {
name: 'q-app',
data () {
return {
flag: 0,
htmlList: [],
select: 'fb',
select1: 'fb1',
multipleSelect: ['goog', 'twtr'],
usersInProject: [],
selectOptions: [
{
label: 'Google',
value: 'goog'
},
{
label: 'Select',
value: 'fb'
},
{
label: 'Twitter',
value: 'twtr'
},
{
label: 'Apple Inc.',
value: 'appl'
},
{
label: 'Oracle',
value: 'ora'
}
],
selectOptions1: [
{
label: 'Integer',
value: 'goog1'
},
{
label: 'Float',
value: 'fb1'
},
{
label: 'String',
value: 'twtr1'
}
]
}
},
methods: {
useRemoveFromProject: function (id) {
console.log('hi....')
Vue.delete(this.htmlList, id)
},
identifyMe: function (event) {
alert('hi - ' + event.target.id)
},
process: function () {
this.flag += 1
let temp = []
temp.push('<div class="card" id="a_' + this.flag + '"> <div class="card-content content-center "> <large id="l4">Expression LHS:</large> <input><br> <large id="l5">Operators:</large> <q-select type="radio" v-model="this.select" :options="this.selectOptions"></q-select><br><large id="l4">Expression RHS:</large> <input><br><large id="l5">Data type:</large> <q-select type="radio" v-model="select1" :options="selectOptions1"></q-select><br></div><button class="cordova-hide circular red " style="margin-bottom:5px; margin-right:30px;" v-on:click="userRemoveFromProject(i)"><i>delete</i></button><input value="click" type="button"> </div>')
let ids = ['a_' + this.flag]
console.log(ids)
this.htmlList.push(temp)
}
}
}
</script>
After looking to your code i noticed that you have some errors:
Call function useRemoveFromProject without the 'r' of 'user'
Call userRemoveFromProject when clicking on the element and not only the delete button
Call userRemoveFromProject(i) with a 'i' variable, but what is 'i' ?
Why using a double v-for? The first level is enough.
I propose to you a working example on a fiddle. Please let me know if it's useful for you (and mark it as resolve if it's the case).
EDIT: for Vue.js 2 https://jsfiddle.net/86216oko/
am having an issue with displaying my Echarts on the second tab. The chart is only displayed on the first tab but on navigation to the second tab it doesn't display
<ul class="nav nav-tabs" style="margin-bottom: 15px;">
<li class="active">
Campaigns
</li>
<li>
Subscribers
</li>
</ul>
<div id="myTabContent" class="tab-content">
<div class="tab-pane fade active in" id="campaign">
<div id="pieChart" style="height:500px;border:1px solid #ccc;padding:10px;"></div>
</div>
<div class="tab-pane fade" id="subscribers">
<div id="barChart" style="height:500px;border:1px solid #ccc;padding:10px;"></div>
</div>
</div>
then hereis the js that displays the chart
var myChart = echarts.init(document.getElementById('pieChart'));
myChart.setTheme({color:['#6CC66C','#418BCA','#ff6600']});
pieChartOption = option = {
title : {
text: 'Campaign Analysis',
subtext: 'Jackpot',
x:'center'
},
tooltip : {
trigger: 'item',
formatter: "{a} <br/>{b} : {c} ({d}%)"
},
legend: {
orient : 'vertical',
x : 'left',
data:['Sent','Pending','Not Delivered']
},
toolbox: {
show : true,
feature : {
mark : {show: true},
dataView : {show: true, readOnly: false},
magicType : {
show: true,
type: ['pie', 'funnel'],
option: {
funnel: {
x: '25%',
width: '50%',
funnelAlign: 'left',
max: 1548
}
}
},
restore : {show: true},
saveAsImage : {show: true}
}
},
calculable : true,
series : [
{
name:'Access Source',
type:'pie',
radius : '55%',
center: ['50%', '60%'],
data:[
{value:{{ $no}}, name:'Sent'},
{value:135, name:'Pending'},
{value:155, name:'Not Delivered'}
]
}
]
};
myChart.setOption(pieChartOption);
/*######################### BARCHART ##################################*/
var myBarChart = echarts.init(document.getElementById('barChart'));
var barChartOption = {
title: {
text: '某地区蒸发量和降水量',
subtext: '纯属虚构'
},
tooltip: {
trigger: 'axis'
},
legend: {
data: ['2014', '2015']
},
toolbox: {
show: true,
feature: {
mark: {
show: true
},
dataView: {
show: true,
readOnly: false
},
magicType: {
show: true,
type: ['line', 'bar']
},
restore: {
show: true
},
saveAsImage: {
show: true
}
}
},
calculable: true,
xAxis: [{
type: 'category',
data: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月']
}],
yAxis: [{
type: 'value'
}],
series: [{
name: '2014',
type: 'bar',
data: [2.0, 4.9, 7.0, 23.2, 25.6, 76.7, 135.6, 162.2, 32.6, 20.0, 6.4, 3.3],
}, {
name: '2015',
type: 'bar',
data: [2.6, 5.9, 9.0, 26.4, 28.7, 70.7, 175.6, 182.2, 48.7, 18.8, 6.0, 2.3],
}]
};
myBarChart.setOption(barChartOption);
/*######################### BARCHART ##################################*/
$(function() {
$( "#tabs" ).tabs({
select: function(event, ui) {
console.log('Calling chart.invalidateSize()');
chart.invalidateSize();
}
});
What cud be the solution to this?
});
ECharts documentation has mentioned
Sometimes charts may be placed in multiple tabs. Those in hidden labels may fail to initialize due to the ignorance of container width and height. So resize should be called manually to get the correct width and height when switching to the corresponding tabs, or specify width/heigth in opts explicitly.
So every time you switch to a new tab, just call the resize function on the chart instance:
chartInstance.resize()
The answer is a little late and I am not sure if you found a solution, but the resolution to this would be a combination of echarts setOption and Bootstrap's Tab event.
Like-
$('#myTabItem').on('shown.bs.tab', function (e) {
myChart.setOption(options);
})
The above code will reload the chart mychart using echarts setOption callback as soon as the Bootstrap Tab is shown. More info on Bootstrap Tab events can be found here.
I have two dojo select dropdowns. First dropdown is populated on page load and on selecting a value from first drop down, second select box should be populated.
I create the second select box programatically and i destroy it for every on change event of the first dropdown box.( this is to avoid widget already registered error).
But when i select any of the option from second drop down select, it does not fire onchange event.
Pls help on this.
My code is
require(["dojo/parser","dijit/form/RadioButton","dojo/ready","dojo/data/ItemFileReadStore","dijit/registry","dijit/form/Select","dojo/ready","dojo/dom-form", "dojo/dom", "dojo/on", "dojo/request","dojo/domReady"],
function(parser,RadioButton,ready,ItemFileReadStore,registry,Select,ready,Form,dom,on,request){
parser.parse();
var manuData;
var modelData;
var shaftType;
var modelId;
var clubMfr;
var clubType;
var manufacturerList;
dojo.connect(dijit.byId("clubtype"),"onChange",function(event){
clubType=registry.byId("clubtype").get('value');
console.log(clubType);
var id= registry.byId("clubtype");
var option1= registry.byId("manufacturer");
request("/tradeIn/"+clubType).then(function(list){
manuData=list;
var data1 = dojo.fromJson(manuData);
var readstore=new ItemFileReadStore({ data:{
identifier : "manufacturer",
label: "manufacturer",
items : data1,
}});
if(typeof registry.byId("manufacturerId") != "undefined"){
registry.byId("manufacturerId").destroyRecursive();
}
manufacturerList=new Select({
name:"manufacturerId",
id:"manufacturerId",
store:readstore,
onSetStore: function() {
this.options.unshift({selected:'true',label:'Choose One', value:'NULL'});
this._loadChildren();
}
}).placeAt("manuList");
manufacturerList.startup();
});
}
);
dojo.connect(
dijit.byId("manufacturerId"),"onChange",function(event){
var manufacturerId=registry.byId("manufacturerId").get('value');
clubMfr=manufacturerId;
var model= registry.byId("model");
model.removeOption(dijit.byId("model").getOptions());
request("/tradeIn/"+manufacturerId+"/"+clubType).then(function(list){
modelData=list;
var data1 = dojo.fromJson(modelData);
var readstore=new ItemFileReadStore({ data:{
identifier : "model",
label: "model",
items : data1
}});
if(typeof registry.byId("modelId") != "undefined"){
registry.byId("modelId").destroyRecursive();
}
var modelList=new Select({
name:"modelId",
id:"modelId",
store:readstore,
onSetStore: function() {
this.options.unshift({selected:'true',label:'Choose One', value:'NULL'});
this._loadChildren();
}
}).placeAt("modelList");
modelList.startup();
});
}
);
dojo.connect(
dijit.byId("model"),"onChange",function(event){
modelId=registry.byId("model").get('value');
console.log("model "+modelId);
}
);
});
You need to disconnect the onChange event before destroying the select and to reconnect it after creating the select. To achieve the disconnection, you can use own() method.
Here is how it should look like:
if(typeof registry.byId("manufacturerId") != "undefined"){
registry.byId("manufacturerId").destroyRecursive();
}
manufacturerList=new Select({/* ... */});
manufacturerList.own(dojo.connect(
dijit.byId("manufacturerId"),"onChange",function(event){ /* ... */ }
));
Note: This is extremely dirty. The proper approach would be to NOT destroy the second select and instead to update its data.
See the snippets for updating it:
require(['dijit/form/Select', 'dojo/data/ItemFileReadStore', 'dojo/domReady!'], function(Select, ItemFileReadStore) {
var initialStoreData = [
{value: "AL", label: "Alabama"},
{value: "AK", label: "Alaska"},
{value: "AZ", label: "Arizona"}
];
var changedStoreData = [
{value: "CA", label: "California"},
{value: "CO", label: "Colorado"},
{value: "CT", label: "Connecticut"}
];
var prepareData = function(storeData) {
//because the store return sorted data, I have added a space before the word 'Choose'. So it comes first
return [{value: '', label: ' Choose one'}].concat(storeData);
}
var readStore=new ItemFileReadStore({
data:{
identifier: "value",
label: "label",
items: prepareData(initialStoreData)
}
});
var selectWidget = new Select({
store: readStore
});
selectWidget.placeAt(document.getElementById('test'));
selectWidget.startup();
btn.onclick = function() {
var newReadStore=new ItemFileReadStore({
data:{
identifier: "value",
label: "label",
items: prepareData(changedStoreData)
}
});
selectWidget.set('store', newReadStore);
}
});
<script src="//ajax.googleapis.com/ajax/libs/dojo/1.10.4/dojo/dojo.js"></script>
<link rel="stylesheet" type="text/css" href="http://ajax.googleapis.com/ajax/libs/dojo/1.10.4/dojo/resources/dojo.css">
<link rel="stylesheet" type="text/css" href="http://ajax.googleapis.com/ajax/libs/dojo/1.10.4/dijit/themes/tundra/tundra.css">
<link rel="stylesheet" type="text/css" href="http://ajax.googleapis.com/ajax/libs/dojo/1.10.4/dojox/form/resources/CheckedMultiSelect.css">
<div id="test" class="tundra">
<button id="btn">change data in select</button>
</div>
I'm trying develop a custom component like that shown in my mockup. I found an example component on the web (might have been in Sencha's docs), and now I'm trying to adapt it for my purposes. I have two questions:
Is this the right approach?
How do I drive my data dynamically from my AlertStore. The example was hard-code with a data: [] value. This can't be bound to a Store?
What I need is like a scrollable list view but with a different type of view. Sort of like the balloons in Apple's iPhone Messages app.
Sample code that I found on the Internet and I'm in the middle of adapting:
Ext.define("Sencha.view.ComponentView", {
extend: 'Ext.Component',
xtype: 'custom-component',
config: {
xtype: 'container',
scrollable: true,
layout: {type: 'vbox', pack: 'start', align: 'stretch'},
cls: ['view1'],
data: {
items: [
{name: 'Congestion near tunnel', n: 100},
{name: 'Car fore near exit 10', n: 21},
{name: 'Broken down vehicle in tunnel', n: 24},
{name: 'Slow traffic next 20 miles', n: 24},
{name: 'Drive carefully', n: 26}
]
},
store: 'AlertStore',
tpl: new Ext.XTemplate(
'<tpl for="items">',
'{% if(xindex % this.getPerRow() == 1) {%}',
'<div class="view-container">',
'{% } %}',
'<div class="alert-row">',
'<div class="name">{[xindex]} - {name}</div>',
'</div>',
'{% if(xindex % this.getPerRow() == 0 || xindex == xcount){ %}',
'</div>',
'{% } %}',
'</tpl>',
{
getPerRow: function () {
return 2;
}
})
},
initialize: function () {
this.callParent(arguments);
}
});
You should just be able to use a list and a css class to add rounded corners to your list items.
Here is a basic fiddle: http://new.senchafiddle.com/#/vZ4fT/
I implemented this chat for this application with Sencha Touch 2:
This is a list with an XTemplate. As #kevhender suggested in his comment, you should let your component inherit from Ext.dataview.DataView (or Ext.dataview.List if you don't need listitems made by more than one component).
Of course you can drive your component with a store, checkout Sencha Docs section on stores. You can basically retrieve your data from a proxy attached to the store, or you can get it from any other source, for example with Ext.Ajax or Ext.data.JsonP, then use setData() on the store. Once you have configured correctly the store the list will automatically update itself when changing its contents.
Here's what I came up with from the provided answers.
Ext.define("SF.view.SampleDataView", {
extend: 'Ext.Container',
xtype: 'sample-view',
id: 'sample-view-id',
requires: [],
config: {
cls: ['class1', 'class2'],
items: [
{
xtype: 'dataview',
cls: 'myclass',
itemTpl: '{name}',
store: {
fields: ['name'],
data: [
{name: 'Congestion near tunnel'},
{name: 'Broken down vehicle in tunnel'},
{name: 'The conference is over. See you next year.'},
{name: 'Slow traffic next 20 miles'},
{name: 'Drive carefully'},
{name: 'Congestion near tunnel'},
{name: 'Broken down vehicle in tunnel'},
{name: 'The conference is over. See you next year.'},
{name: 'Slow traffic next 20 miles'},
{name: 'Drive carefully'}
]
}
}
]
},
initialize: function () {
this.callParent(arguments);
}
});
I also added some margin and padding to #bwags' css.
.customRound {
border:2px solid;
border-radius:25px;
margin: 30px;
padding: 10px;
}