What causes circled ! in Sencha ExtJS Example? - extjs

I'm trying to mimic the behavior of the Sencha ExtJS example at this URL:
http://examples.sencha.com/extjs/6.0.2/examples/kitchensink/#form-contact
Specifically, they show the code but I don't see any place that cause the circled red exclamation point to be drawn whent he field is required.
I'm also wondering if there is a better way to get the red "*" after each field label. It looks like they repeat the code on every field definition which feels like an anti-pattern to me.
***UPDATE
Per #CD, this is how to get the red icon
defaults: {
anchor: '100%',
labelStyle: 'font-weight:bold;padding:0;',
msgTarget: 'side'
},

For the error icon have a look at msgTarget: 'side':
The location where the error message text should display. Must be one
of the following values:
qtip Display a quick tip containing the message when the user hovers
over the field. This is the default.
Ext.tip.QuickTipManager.init must have been called for this setting to
work.
title Display the message in a default browser title attribute popup.
under Add a block div beneath the field containing the error message.
side Add an error icon to the right of the field, displaying the message in a popup on hover.
none Don't display any error message. This might be useful if you are implementing custom error display.
[element id] Add the error message directly to the innerHTML of the specified element.
For adding the red "*" try this override:
Ext.define('Overrides.form.field.Base', {
override: 'Ext.form.field.Base',
initLabelable: function () {
this.callParent(arguments);
if (!this.allowBlank) {
this.labelSeparator += '<span style="color: rgb(255, 0, 0); padding-left: 2px;">*</span>';
}
}
});

Related

Bootstrap dropdown in column header

I've been trying to use the ng-grid 3.0 (ui-grid). I have managed to populate my grid and it's been very responsive and it's features are really amazing. But I'm trying to customize my column headers, as I need more info there.
I can create a custom header cell template, as indicated in the docs, but I don't seem able to use a Bootstrap Dropdown there, it gets cropped and I can't use it at all. Some googling got me thinking it is probably some issue with the overflow attributes, but still I can't solve it. My grid options is as follows:
$scope.columnDefs = [
{ name:'name', displayName: 'Vdd', headerCellTemplate: 'headerTemplate.html' },
{ name:'gender', headerCellTemplate: 'headerTemplate.html' },
{ name:'company' }
]
$scope.gridOptions = {
columnDefs: $scope.columnDefs,
rowTemplate: 'rowTemplate.html',
data: 'data'
};
I have forked an example in plunkr and managed to reproduce my issue:
http://plnkr.co/edit/qdrFiifiz18fxB8w6Aja?p=preview
I want to replace the built-in dropdown menu (since it doesn't seem to allow nesting and sub-menus) and add another one (so in the end, I'd have two dropdown menus in each header cell)
Any help is appreciated =)
I am proud to say I think I've figured it out. I've been digging through ui-grid's source code and narrowed it down to this block (lines: 2847 - 2852).
function syncHorizontalHeader(scrollEvent){
var newScrollLeft = scrollEvent.getNewScrollLeft(colContainer, containerCtrl.viewport);
if (containerCtrl.headerViewport) {
containerCtrl.headerViewport.scrollLeft = gridUtil.denormalizeScrollLeft(containerCtrl.viewport,newScrollLeft, grid);
}
}
I noticed that containerCtrl.headerViewport.scrollLeft was never getting set to newScrollLeft. A quick google search led me to this StackOverflow thread which says that you can't set the scrollLeft property of an element if it's overflow is set to visible.
My solution was to replace containerCtrl.headerViewport.scrollLeft = gridUtil.denormalizeScrollLeft(containerCtrl.viewport,newScrollLeft, grid); with containerCtrl.headerViewport.style.marginLeft = -gridUtil.denormalizeScrollLeft(containerCtrl.viewport,newScrollLeft, grid) + 'px'; which just sets a negative margin on the header. Then add an overflow:hidden; style to .ui-grid-render-container-body to hide headers that extend beyond the main grid viewport.
Doing this messed up the placement of column menus, but there is an easy fix. On line 514 replace var containerScrollLeft = renderContainerElm.querySelectorAll('.ui-grid-viewport')[0].scrollLeft; with var containerScrollLeft = renderContainerElm.querySelectorAll('.ui-grid-viewport')[0].style.marginLeft; to use the margin instead of the scroll value in the menu placement calculation.

Why there is time lag when using Kendo and angular JS

I am newbie to Angular and Kendo,My case is like buttons other than edit must disappear for other users in the query screen and it should appear for the owner of the query alone.
Now it disappears after some time lag say one minute,why this lag occur?
Any help on this is greatly helpful for me....
On analysis,identified the below points:
-the function called in ng-show is not triggered immediately where ng-show is wrapped inside a template,then checked by assigning a constant value for ng-show still there is a delay in triggering the ng-show.But fixed style worked correctly example style=display:none..
-then i identified that angularjs directives are not invoked immediately after rendering kendoui grid row template, there is some delay to invoke the angularjs directives
Code:
$scope.showButton = function(userId){
if($scope.loggedInUserId == userId)
{
return true;
}
else
{
return false;
}
};
$scope.model.columns = [
{ field: "name",title:"Name", width: 300},
{ field: "userId",title:"User Id", width: 100},
{ field: "lastModified",title:"Last Modified Date", width: 200},
{ field: "visibility",title:"Visibility", width: 100},
{ template: "<img title='Edit' src='content/images/glacier/2.0.1/generic/normal/png21/d_040_edit_normal.png' onmouseover=\"this.src='content/images/glacier/2.0.1/generic/active/png21/d_040_edit_active.png'\" onmouseout=\"this.src='content/images/glacier/2.0.1/generic/normal/png21/d_040_edit_normal.png'\" ng-click='viewQuery(#=id#);disableSave(\"#=userId#\")' alt='Edit'><img title='Make Public' src='content/images/glacier/2.0.1/generic/normal/png21/d_150_team_normal.png' onmouseover=\"this.src='content/images/glacier/2.0.1/generic/active/png21/d_150_team_active.png'\" onmouseout=\"this.src='content/images/glacier/2.0.1/generic/normal/png21/d_150_team_normal.png'\" ng-click='makePublic(#=id#)' ng-show='showButton(\"#=userId#\")' alt='Public'><img title='Make Private' src='content/images/glacier/2.0.1/generic/normal/png21/d_118_user_normal.png' onmouseover=\"this.src='content/images/glacier/2.0.1/generic/active/png21/d_118_user_active.png'\" onmouseout=\"this.src='content/images/glacier/2.0.1/generic/normal/png21/d_118_user_normal.png'\" ng-click='makePrivate(#=id#)' ng-show='showButton(\"#=userId#\")' alt='Private'><img title='Delete' src='content/images/glacier/2.0.1/generic/normal/png21/d_030_delete_normal.png' onmouseover=\"this.src='content/images/glacier/2.0.1/generic/active/png21/d_030_delete_active.png'\" onmouseout=\"this.src='content/images/glacier/2.0.1/generic/normal/png21/d_030_delete_normal.png'\" ng-click='deleteQuery(#=id#)\' ng-show='showButton(\"#=userId#\")' alt='Delete'>", title: "Operations" },
];
$scope.model.gridOpts = {
columns: $scope.model.columns,
filterable: { extra: false },
scrollable: true,
height: "230%",
pageable: true,
batch: false,
reorderable: true,
sortable: true,
editable: "inline",
};
Without having a JSFiddle to analyze, it will be hard to pin down the problem. But I'll provide a possible solution that you can at least investigate.
Angular is only able to hide those buttons after it, and everything it depends on, has started up. Which means downloading the angular code, waiting for everything else to load, parsing the HTML, resolving any data dependencies, etc. At that point it will make modifications to the DOM (which is when your buttons hide).
There are several ways to handle this, from using ng-cloak, not showing anything on the screen until it's been modified appropriately, or hiding all the optional controls and just showing what the user does have access to after Angular loads.
Here is one option which I just used in a project. Add this code at the TOP of your entry file (like index.html, default.html, whatever):
.ng-hide {
display: none !important;
}
Now apply the ng-hide class to any of those buttons you don't want to show until you know what they have access to.
By placing this at the top of the default file, it won't show at all until it's told to. If you place it in a .css file, then it will sometimes appear briefly until the .css file it loaded, parsed and applied.
Another option is to look at ng-cloak. You can try out it out here: http://plnkr.co/edit/?p=preview
The fact that it's taking upwards of 60 seconds I believe you said, leads me to believe that maybe it is waiting for required data to get resolved before it can analyze permissions.
If you don't understand how the resolve statement works in routes, you can read about here:
http://www.undefinednull.com/2014/02/17/resolve-in-angularjs-routes-explained-as-story/
I'm not sure if that will fix your problem, but once you can create a jsfiddle then you'll have many more people jumping in to answer this question.

Clear the Search Text field in LiveSearchGridPanel

We are using the LiveSearchGrid Panel in ExtJS 4.2.1 similar to the example below, with Pagination. When the user searches for a record in one page, and then goes to another page, the search text field is NOT cleared, and clicking on the next or previous buttons show some random results (which are based the previous search). How can I clear this Search Text Field in the LiveSearchGridPanel?
http://dev.sencha.com/deploy/ext-4.0.1/examples/grid/live-search-grid.html
I looked into the API documentation of LiveSearchGridPanel, but it does not provide an easy handle to the Search Text Field.
Add a listener on the beforechange event of the paging toolbar. Something like this:
{
xtype: 'pagingtoolbar',
// ...
listeners: {
beforechange: function() {
this.up('grid').down('textfield[name=searchField]').setValue('');
}
}
}

Ext ComponentQuery wildcards

I've searched the examples and docs and I couldn't find if its possible to use wildcards in the ComponentQuery query. Id like to do the following:
Ext.ComponentQuery.query('button > menu > menuitem[text="Welcome*"]');
Since the button text will be the current user name for example "Welcome Shaun".
Try
Ext.ComponentQuery.query('menuitem{text.search( \'Menu Item\' )!=-1}');
Per the docs, you can use custom expressions. This works for the code I've included below:
var toolbar = Ext.widget('toolbar', {
items : [
{
xtype:'splitbutton',
text: 'Menu Button',
iconCls: 'add16',
menu: [{text: 'Menu Item 1'},{text: 'Menu Item 2'}],
reorderable: false
},
{
xtype: 'button',
text: 'Get matches',
handler: function(){
var match = Ext.ComponentQuery.query('menuitem{text.search( \'Menu Item\' )!=-1}');
console.log( match )
}
}
]
});
Ext.widget('panel', {
renderTo: Ext.getBody(),
tbar : toolbar,
border : true,
width : 600,
height : 400
});
Just for the sake of completeness (and because Member Expressions can crash the query)
As #existdissolve stated you can archive something similar (not the same!) of a wildcard with the use of a Member Expression like in your case
Ext.ComponentQuery.query('button > menu > menuitem{text.search("Welcome")!=-1}');
This will try to perform the native JS search operation on the text property of any found menuitem. No matter if this property exist (or the method) which brings me to the main issue of Member Expressions
What you need to know about Member Expressions
You can use a Member Expressions on nearly every selector but they need to exist on that selector or you end up with a exception which aborts the query (totally, like a exception does).
Here's a simple example. Let's say you want to find a button by it's text. That should be no problem, all buttons need a text, didn't they? This works for quite a time till your customer complains that some buttons don't need text a simple image would be enough. You have forgotten about the query thing and add the button and suddenly parts of your application stop working while you end up with a exception like
Uncaught TypeError: Cannot call method 'search' of undefined
You can try it yourself in this JSFiddle example. Try 'find me' and after that hit the 'add image button' and try it again.
Why does this happen? The Ext.ComponentQuery test neither if property exist nor if the expression exist which can quickly lead to a total fail of the query.
Yes, the example above is simple and you may find the source of the error real quick but it can also be completely different.
What now? I don't want to say to say that you should not use a Member Expression but you really need to care about the side effects that you may face.
Starting with ExtJS 5 functionality was introduced that makes this task much cleaner by allowing matching via regular expressions. The documentation provides further detail, but a solution that solves the posted question would look like this:
Ext.ComponentQuery.query('button > menu > menuitem[text/="^Welcome"]');

Delete treegrid icon

I won't show treegrid icon each node.
I tried using:
1. "iconCls" config, with 'void' value.
2. Using a 'wrong' value.
Finally, I have the same that I expected, 'defaults icons' for all rows.
Someone know any form to delete these icons ?
thanks for all.
Just make sure you give an iconCls of, say treenode-no-icon. I do so in my model:
{name: 'iconCls', type: 'string', defaultValue: 'treenode-no-icon'},
Then in your css include:
.treenode-no-icon
{
display : none !important;
}
This was a few years ago, but here is a solution using ExtJS 6 that I discovered.
Using a custom theme, in the theme file associated with Ext.tree.View, I added the line:
$tree-icon-width : 0px;
My treepanel data now displays without any visible icons.

Resources