Extjs 4.1 pagingtoolbar default page - javascript

I want to change default page of pagination toolbar to 1 of 1 instead 0 of 0 in case of no record.Plus I am not using store proxy to request any records, so is there any way to accomplish it without using store proxy. According to my requirement user can add rows manually to the grid with the pagination toolbar showing page 1 and when rows exceeds 10 it moves to 2nd page.

In Ext it is possible to overload a component like Ext.toolbar.Paging with your own custom version. Simply specify an alias in your definition and you can us it just like the "native control."
In order to be sure that the approach would work, I set up a test project with a simple datasource and implemented enough of a replacement definition that I could see the "Ext.toolbar.Paging".getPagingItems method being fired in my custom definition.
From that point you can replace the code inside the definition of the original method to allow for a custom minimum in addition to the opportunity to overload the "updateInfo" method to make sure that during data reloads you're not plowing through your customizations.
In addition to these two things, you should (with a relatively small amount of effort) be able to implement on top of the control to support dynamically changing it's values based on the contents of your grid.
If you look at the documentation for ux.data.PagingStore you should be able to suss out the differences in using a remotely supplied store from something that is served with data locally.
Hope this helps you.
Code Sample:
Ext.define(
"Test.view.testview.TvPageBar",
{
extend: "Ext.toolbar.Paging",
alias: "widget.tvpagebar",
title: "Bob",
strictInit: function () {
"use strict";
console.log("TvPageBar init");
},
getPagingItems: function () {
console.log("getPagingItems", this);
this.callParent(arguments);
},
initComponent: function () {
this.strictInit();
this.callParent(arguments);
}
}
);

Related

One view for 2 or more pages (backbone.js)

I have two pages. One of them is dashboard with a lot of functionality. The second page is shared dashboard - the simple version of the first page.
The dashboard contains the view of the database (it can contain much other info, but the problem with this one). You can click on the filter button and modal window will be opened. So, simple version of the dashboard doesn't have this possibility. I'd like to add it, but I don't want to copy+past code from the full version of the dashboard because the code of this part is about two thousand lines. I'll add some primitive code example:
DashboardView = SomeAnotherView.extend({
initialize: function() {...},
events: {...} // huge objects of jQuery events,
render: function () {...},
... // 2k lines of functions for events
});
How can I use this View on another page? I tried to call a function from this view:
DashboardView.prototype.filterClicked(event);
But in this case event.curentTarget is null (it is necessary for this function), I also tried to send "this" to get the context, but it was failed.
Is there a possibility in Backbone.js to use one View for 2+ pages without any huge copy/past code?
Ideally if you have a simple version and full version of a view, you should have a "base view" (simple one) and the full version should extend the base view.
It'll look something like:
var SimpleDashbard = Backbone.view.extend({});
var Dashboard = SimpleDashbard.extend({});
In this way Dashboard will have access to the methods from SimpleDashbard.
Your situation sounds like you need to use a method from extended view in base view. Which is not a good idea. Ideally if it's shared you should move it to the base view/extract it into a utility method or service, and of course this involve re-writing this method to be reusable
If you have views that share a large amount of functionality, you could consider using the same View type, but opening it up to some configuration when instancing. For example:
var DashboardView = Backbone.View.extend({
initialize: function(options) {
this.allowFunctionX = (options && options.allowFunctionX);
this.allowFunctionY = (options && options.allowFunctionY);
},
// etc
functionX: function() {
if (!this.allowFunctionX) { return; }
// do the function...
},
functionY: function() {
if (!this.allowFunctionY) { return; }
// do the function...
},
});
Then on one page:
var firstDashView = new DashboardView({allowFunctionX: true});
and on another page:
var secondDashView = new DashboardView({allowFunctionY: true});
This may become not worth it if the functionality diverges too much (and there are likely better ways to configure than passing in a long list of booleans!). If your requirements are significantly different on your two pages, I feel like duplicating the code they both need is not a major sin.

selectively using different range sliders using Algolia instantsearch.js

With Algolia Instantsearch.js I'm looking to selectively use different rangeSliders depending on the value of a passed country_code parameter in the query string.
If e.g: the country_code is 'FR' I want to use a total_area_meters range slider, and use another range slider that uses euros. For the 'UK' I want to use total_area_ft and another range slider that uses pounds.
Though I'm waiting (and hoping) for https://github.com/algolia/instantsearch.js/issues/753 to be implemented, I've been told by Algolia support personnel that it's potentially possible to use the helper library: https://github.com/algolia/algoliasearch-helper-js to get this working.
I have e.g: experimented with selectively enabling disjunctive facets using:
search.addWidget({
init: function (opts) {
// opts.helper contains the underlying algoliasearchHelper
if(detected_locale === 'fr'){
opts.helper.setQueryParameter('disjunctiveFacets', [
'total_area_meters','price_eur'
]);
//...
Though doing this is not enough: among other issues, there are still slider widgets on the page e.g: requiring 'total_area_feet, and 'price_gbp' which raise javascript errors - I need to disable them somehow, and also there are quite obtrusive urls that need to be selectively removed.
e.g: If my disjunctive facet is: total_area_meters: I get a url like this:
&nR[total_area_meters][>=][0]=135&nR[total_area_meters][<=][0]=770 - which needs to be removed when I have a country_code where feet are used, instead.
So my questions about this are:
Is there a way to selectively enable/disable instantsearch.js rangeslider widgets programmatically via js? (or can I somehow programmatically set their values/ reset them so they have no query parameters?)
If not covered in the solution above, are there any pre-built functions for me to clean up the rangeslider url parameters? Thank you!
With help from Tim Carry at Algolia, I was able to get a work-around working. It's not perfect, but in a nutshell, I first added all my sliders to the page. I then selectively hid them using:
.hideClass {
display: none;
}
$sliders[i].addClass('hideClass');
// or
$sliders[i].removeClass('hideClass');
This performs much better than:
$sliders[i].show()
//and
$sliders[i].hide()
Depending on the country_code in the url.
I found that it's (unfortunately) necessary to re-issue hiding/showing commands on each render call (not just on init()) e.g:
search.addWidget( {
render: function(opts) {
show_hide_sliders();
}
});
It's possible to remove all url parameters for a slider using:
helper.removeNumericRefinement(slider_attribute[i]);
which is only issued if there is a country_code change.
And it pretty-much seems to function (though caveat: only limited testing so far). Hope this is helpful to someone.
EDIT:
To respond to the comments, a note: in this case I got a handle on the helper by using opts.helper (but I probably might have also succeeded using search.helper, too.). e.g:
search.addWidget( {
render: function(opts) {
show_hide_sliders();
opts.helper. ... // add your helper methods...
}
});

How to remove the "name" param in for fields in ExtJS 4

I am integrating a payment provider into a ExtJS websites.
Basically, a form needs to be created and the form fields is send to the payment provider using Ajax.
The problem is that the payment provider does not allow that the form fields has a "name" param assigned to the "" tag. They do a manual check of the implementation and makes sure it is not there.
I assume it is a counter-mesasure for when the visitor has Ajax dissabled and the form gets submitted to my server instead, revealing the credit card. I know it does not make any sense with ExtJS, as it would not work without Javascript turned on, but non-the-less, that is the rule from the payment provider.
So, how can I force ExtJS to not put a "name" param in the form field? I have tried putting "name: ''" into the fields, but that gets ignored.
Do I use the template-system in ExtJS to solve this?
So Eric is perfectly right that it can be done much easier then modifying the whole template but non the less I would use a plugin for such a special case. I made a quick one:
Ext.define('Ext.form.field.plugin.NoNameAttribute', {
extend: 'Ext.AbstractPlugin',
alias: 'plugin.nonameattribute',
init: function(cmp) {
Ext.Function.interceptAfterCust(cmp, "getSubTplData", function(data){
delete data['name'];
return data;
});
}
});
Note the used method interceptAfterCust is a custom one of mine that modify the existing one by handing the result of the original to the intercepting one as argument. It is also using the given original object (which can be threaten as a scope) as scope for the original method. The easiest would be to add these method to Ext.Function
Ext.Function.interceptAfterCust = function(object, methodName, fn, scope) {
var method = object[methodName] || Ext.emptyFn;
return (object[methodName] = function() {
return fn.call(scope || this, method.apply(object, arguments));
});
}
Here is a working JSFiddle where the first field will not have a name attribute on the dom even if it exist in the component.
There's a surprisingly simple solution to this. I tested it with Ext.form.field.Text and Ext.form.field.ComboBox and it works well, but I don't know if it works for all form fields or if there are any negative side-effects. Use with caution.
Ext.define('Override.form.field.Base', {
override: 'Ext.form.field.Base',
getSubTplData: function(){
var data = this.callParent(arguments);
delete data.name;
return data;
}
});
Basically, it removes the auto-generated name from the render data before passing it along. The best part is that no private methods are involved so this should be a stable solution.
I prefer this in the field config options:
submitValue: false
Available since ExtJS 3.4

How to (properly) render additional data in grid with RowExpander

I'm trying to render some data in the rowbody in a grid (with the RowExpander plugin).
My problem is that the ol' rowBodyTpl isn't enough for me as this data is from Records on Stores from the record being rendered (hmmm...).
Putting it simply: Every record of the grid has a store in it (lets call it Items). So, I want to render the record data and some data of the Items records aswell.
What would be the best(ish) way of doing so?
Override the renderer function of the rowexpander plugin, override the getAdditionalData, or none of these?
Thank you.
I know this question is a few years old, but here's a trick I currently use to handle this kind of situation. It takes advantage of "verbatim" blocks that XTemplates allow. These allow you to execute arbitrary code inside an XTemplate by wrapping it with {% ... %}. Inside those code blocks, this is set to the XTemplate itself. The XTemplate has an owner property that, in our case, references the RowExpander plugin itself, which, in turn, has a grid property to reference the grid. So, something like this allows you to add arbitrary data to the values passed into rowBodyTpl.
Ext.create('Ext.grid.Panel', {
...
injectRowBodyData: function(values) {
values.MyInjectedContent = "Here's some extra data!";
},
plugins: [
{
ptype: 'rowexpander',
rowBodyTpl: [
'{% this.owner.grid.injectRowBodyData(value); %}',
'<div>',
'<h1>{Title}</h1>',
'<p>{Content}</p>,
'<p>{MyInjectedContent}</p>',
'</div>'
]
}
]
});
Hhopefully Sencha will fix the plugin to provide a way to handle this in the future. But for now this works well. I tested this with v4.2.1.883, but this should work with any previous version of Ext 4. The only thing I can think of that may prevent it from working in the future is the XTemplate's owner property no longer being pointed to the plugin, or the plugin not having a reference to the grid with it's grid property.
How I "solve" this problem, it might help somebody else:
I overrode the getRowBodyFeatureData of the rowexpander plugin, as this function not only receives the data to be applied on the template, but also the record itself, so I just data added the extra stores/arrays from the record.
Not sure if its the best way, but hey... at least it works.
You can also use if else statements in rowBodyTpl:
Check for ":"
"<tpl if='phone == \":\"'>",
"<tpl else>",
"</tpl>"
Check for empty string
"<tpl if='phone == \"\"'>",
"</tpl>"
this sample is taken from here: link
This is how I usually do:
Ext.create('Ext.grid.Panel',{
border: true,
store: 'ds',
columns: []
plugins: [{
ptype: 'rowexpander',
rowBodyTpl : ['<p><b>Title:</b>{name}<br/><b>Description:</b> {description}<br/><b>Experiment Design:</b> {experimentdesign}</p>']
}],
renderTo:
});

Dojo widget defaults

i'm currently writing a large scale application heavily based on the dojo toolkit. The whole app is working and standing, but one issue i can not find my way out with, is the creation of custom widgets. It would be useful because it would clean up my source code and also i can reuse this 'widgets' in later projects.
For example: i have a main toolbar, which i would like to call using
myapp.toolbar = new myapp.mainToolbar();
instead of using
myapp.toolbar = new new dijit.Toolbar({}, containerID);
var button1 = new dijit.form.Button({
label: 'Delete',
id: 'toolbarbutton1',
showLabel: true,
iconClass: "dijitEditorIcon dijitEditorIcon Delete"
});
myapp.toolbar.addChild(button1);
...
So in short: how do i set up the whole toolbar somewhere else and call it as a simple object? Trying to figure out dojo.declare('myapp.mainToolbar', dijit.Toolbar, {...}) but then i get a bunch of errors like 'startup function not existing' etc...
I'd like to do all this programmatically, so without the template html and css files in a custom widget.
A link to a good tutorial or howto would be nice, although google nor yahoo! will reveal any extra's on this matter for me... :)
There are multiple ways to do this.
It seems like your method of extending Toolbar should work (not sure why it didn't).
You can also declare a class that embeds Toolbar and the buttons, using widgetsInTemplate:
dojo.declare("MyToolbar", [dijit._Widget, dijit._Templated], {
_widgetsInTemplate: true,
templateString: '<div> <div dojoType=dijit.Toolbar>' +
' <button dojoType=dijit.form.Button ...
Note that the top node in MyToolbar can't have a dojoType, so I put Toolbar one level down.
Alternately you can do the same thing by using dijit.Declaration, see http://docs.dojocampus.org/dijit/Declaration.
It works for me when I use declare with the superclass inside of an array:
dojo.declare('myapp.mainToolbar', [ dijit.Toolbar ],
{
....
}
);
var x = new myapp.mainToolbar({ ... });
x.startup();
Which kind of violates the docs. It should take one Function or an array of Functions.

Categories

Resources