extjsGirdPanel.getView().getRowClass does not work 2nd time - extjs

The handler of an extjsAction button calls a function with following code.
Add: function() {
var window = Ext.getCmp('wndAdd');
window.items.items[0].getStore().reload;
var Grid1 = Ext.getCmp('grdAll');
var grdStore2 = Ext.getCmp('grid2').getStore();
var i = 0;
var IDList = new Array();
for (i = 0; i < grdStore2.data.length; i++) {
IDList[i] =
grdStore2.data.items[i].data['ID'];
}
Grid1.getView().getRowClass = function(record, index) {
if (IDList.contains(record.data["ID"])) {
return 'disabled-row';
}
};
window.show();
}
But the getRowClass function works only on the first button click. does ot disable the row which gets added.

getRowClass only needs to be assigned one time. It is not a function that you call, it is a function called internally by the grid every time a row is rendered. Rather than assigning it inside an event handling function, it should be assigned ONE time, somewhere at the application level (e.g., wherever Grid1 itself is first configured would be the most logical place). This may or may not be your issue, depending on how your Add function is getting called, which is not clear. Bear in mind that since you rely on IDList inside getRowClass, you'll also have to have a reference to that variable that is in scope where the function is, and you will probably also have to add checks to make sure it is valid before accessing it.
You are also not showing where Grid1 is getting re-rendered. As explained above, getRowClass only executes when rows are rendered, so unless you are refreshing Grid1 somewhere not shown in your code, getRowClass will never be called.

FYI, while I'm glad that you found a solution that works for you, I'm not sure you understand getRowClass still. It does NOT get called only once -- it gets called EVERY time a grid row is re-rendered (which is anytime data changes). It was only getting called once in YOUR code because your code was not set up correctly.
I don't fully understand your use case, but regardless of the window being shown, the row striping would only need to change if the grid's underlying data actually changed. When you set up the getRowClass function properly, the grid takes care of calling it for you automatically, when it needs to, and it should "just work." There should be no need for your iteration code as written which just adds extra overhead.
Again, just FYI. :)

Yes, the getRowClass gets called only once when the grid is configured. But I wanted something that would fire everytimewindow.show() gets fired. I used the below code on window.onshow event.
for (var i = 0; i < Grid1.getStore().data.length; i++) {
var element = Ext.get(Grid1.getView().getRow(i));
var record = Grid1.getStore().getAt(i);
if (IdList.contains(record.data.ID)) {
element.addClass('disabled-row')
} else {
element.removeClass('disabled-row')
}
}

I will edit my response with an appropriate answer once supplied more information.
When are you firing getRowClass? It seems like you are creating the function but never actually calling to for a response.
Does the function error out, get called at all, or just doesn't do what you want?

Related

Changing variable without influencing view

I am displaying a view (ui-router) on the Ionic platform with a message list. New messages should be shown as unread, but then corresponding variables should be changed to read. The problem is that when I set the controller to change the proper variable, the view automatically updates itself immediately with this change and the messages are immediately displayed as read.
How can I deal with this?
In other words: in a variable-dependent view, I want to display the view first and then modify the variable, so that the change of the variable does not affect the view.
The current code (MarkAsRead() is called from within the template):
$scope.messages = $rootScope.Messages.Inbox;
$scope.MarkAsRead = function(ID_NR)
{
angular.forEach($rootScope.Messages.Inbox, function (value, key) {
if ((value.IsRead == 2) && (value.From == ID_NR))
{
value.IsRead = 3;
}
});
}
It's odd you're battling the main thing angular is known for: two-way binding. That said, if you really want to make changes to the variable without updating the view, you can use angular.copy to make a deep copy of the object and manipulate the copy itself. Or display the copy but manipulate the original
Another option, if you're using Angular > 1.3, you can use one-time binding to only update the view first time:
Simply prefix your expression with :: e.g
<p>{{::message.IsRead}}</p>
https://docs.angularjs.org/guide/expression#one-time-binding

Mutating object properties within an array with Polymer

I not sure how to solve this issue. I am sure someone will know this very quickly.
I have an array of objects and modifying a property. I have a firebase listener 'child_changed'. When firebase is updated need to update the array. Here is the code below.
dbRefList.on('child_changed', function(snap) {
var len = this.grocerylist.length;
for(var i=len; i--;) {
if(this.grocerylist[i].key === snap.key) {
this.set(['grocerylist', i, 'selected'], snap.val().selected);
}
}
this.notifyPath('grocerylist', this.grocerylist.slice());
}.bind(this));
When the array is modified I want the template repeat-dom to trigger. I know this.set will not trigger array mutation sub properties but again I am not sure how to solve this. I done research and tried so many solutions.
I can force a render on the template dom-repeat but I would prefer the data binding way.
So this code (just the this.set you have in there now) should cause the value of grocerylist.i.selected to update inside the dom-repeat (assuming it's bound in there so it's actually showing up).
What behavior are you seeing? Are you trying to filter or sort the list based on the selected value? In that case, you might need to add observe="selected" on the dom-repeat.
(Also—have you confirmed that the child-changed callback is being called with the this value you expect—the element—rather than window or something else?)
You should be able to force a refresh by doing this.grocerylist = this.grocerylist.slice() or this.set('grocerylist', this.grocerylist.slice()); ... notifyPath doesn't work here because notifyPath doesn't change the value, it notifies the element about a prior change (the second argument is effectively ignored).

Angular - Prevent event looping?

I need your help as I am still having trouble with events handling.
Here is the concept :
To contextualize, let's say that I have visuals items, that I call "components".
A component is defined by 2 javascript objects. One is containing data (like position x, y, width, height, color, etc...). The other one is the view exploiting a 3rd party library named draw2d.
Draw2d uses it's own x y width height color etc... properties. Which mean that I need to "bind" values to always keep them equals.
For this purpose, I just use events. There are 'on' events in draw2d letting me watch theses modifications. For the angular side, I just use the ng-model directive directly on my data bindings. When a data is updated, I update draw2d view, and when the view is edited, I update my data.
This part is working correctly as this is not hard to handle it.
I then tried to implement multiple selection editing. For that, I store in an array every selected component. When a value from the view or from the data is edited, I trig an event which let every selected component to set the same data to the same value. Again, it's working great.
Where i'm starting to struggle hard, it's when I want to edit the position. I don't want every components to be on top of each other. For that, when I edit multiple x or y attributes, instead of positioning elements, I calculate the offset so that every components move with this offset only. Here is where it's not okay. Of course, when an offset is set, others components updates, also trigging their new value, so I'm stuck in a hell loop.
I would like to know if you know any pattern to handle events so that, when you have 2 view and a model, you can stop an event from propagate.
Here is my propagation snippet :
scope.canvas.on('figureEdited', function (canvas, event) {
if (scope.selectedComponents.length > 1) {
var key = event.key;
var value = event.value;
var originComponent = event.origin;
for (var i = 0; i < scope.selectedComponents.length; i++) {
var selectedComponent = scope.selectedComponents[i];
if (selectedComponent !== originComponent) {
if (key !== 'x' && key !== 'y') {
selectedComponent.setData(key, value);
} else {
var offset = value - event.oldValue;
selectedComponent.setData(key, selectedComponent.getData(key) + offset, true);
}
}
}
}
});
the issue is caused by
selectedComponent.setData(key, selectedComponent.getData(key) + offset, true);
It retriggers a figureEdited event, making every component move again by this offset, infinitely (stopped by 10 digest iterations).
I hope this is clear, sorry for the long text and thanks a lot for your help :)
Alann.
If the setData call triggers new events synchronously you can ignore events triggered while in your loop by setting an ignore flag and checking it at the start of the function.
var ignoreEvent = false;
scope.canvas.on('figureEdited', function (canvas, event) {
if (ignoreEvent) return;
ignoreEvent = true;
//...
ignoreEvent = false;
});

remove event listener as3

I'm almost finished with a quiz of mine. I've encountered an error which I have finally pinpointed. But first I'll tell you some background info on the code.
Background
On stage, there exist 4 button components registered as movie clips. These are later stored in an array. When a certain icon is clicked on stage, these buttons are to be activated by adding event listeners to all of them. When a button is pressed, it checks if it's the 'correct' answer and removes the event listeners.
Now I have done extensive checks and narrowed down the problem to the following.
Code
This function will add button listeners to each button recursively. Note that the variable 'num' is a fixed integer between 1 - 4 which is generated earlier into the code and used for many 'if' cases.
function addButtonListener(num:int):void
{
for (var obj:Object in _buttons)
{
_buttons[obj].addEventListener(MouseEvent.CLICK, checkans(num));
}
}
This function is basically the opposite and also disables the buttons
function removeButtonListener(num:int):void
{
for (var obj:Object in _buttons)
{
_buttons[obj].removeEventListener(MouseEvent.CLICK, checkans(num));
_buttons[obj].enabled = false;
}
}
Now one thing I noticed through the use of trace functions is that the code correctly adds the button listeners but it does not remove them.
This function calls for each button to be removed.
function checkans(num:int):Function
{
return function(e:MouseEvent):void
{
if (e.currentTarget.label == xmlNodes)
{
points = points + (2 * num);
scoreBox.text = points.toString();
}
else
{
trace("Incorrect!");
}
if(myText.parent){
myText.parent.removeChild(myText)
}
closeShowQuestion(num);//closes a previous function
removeButtonListener(num);//Should I pass this variable into the end function?
GoFishing.addEventListener(MouseEvent.CLICK, fish);//Starts the process again.
}
}
So am I removing the event listeners incorrectly?
Do you need to see more code to be sure?
Thanks in advance!
removeEventListener must use the SAME function that was used in addEventListener.
Your checkans function always returns a NEW function, so it will not be the same for add and remove.
If you have to pass a num into your listener function, do it other way. Make it a property of a button or store externally etc.

GetProperty problem

I have an ASP.net website and inside its .aspx page there is a javascript function
and from my silverlight project , i want to get a value of property in the javascript funcion
i used "eval" to evaluate the function and GetProperty to return the value i want
the problem is GetProperty work only if i call the function for the second time
but never return in the first call
javascript code:
function RETURNIMAGE() {
var x = { value: document.getElementById("ImageContainer").value };
return x; }
c# code:
string getImage = "document.getElementById('myIFrame').contentWindow.RETURNIMAGE ();";
ScriptObject imgObject = HtmlPage.Window.Eval(getImage) as ScriptObject;
var img = imgObject.GetProperty("value");
any help please?
Since it works the second time I strongly suspect that the first time the IFrame is still loading its contents. Both Silverlight and the Browser will be getting on with their various activities asynchronously from each other.
Here is something that might help to halt the code until the page loads:
A hidden object/property can be put in the frame, but make sure it is after the property to be fetched.
Then a 'while' loop can be inserted in the c# code to check that this hidden property exists (the loop breaks only when the property value is loaded correctly), then put the rest of your code after the while loop.
This solution may not be optimum, but may be used to check if it is a loading problem or not.

Resources