In extjs GridFilters.js, we have :
onStateChange : function (event, filter) {
......
...
if ((this.autoReload || this.local) && !this.applyingState) {
//alert('Firing reload');
this.deferredUpdate.delay(this.updateBuffer);
}
}
I thought this means that whenever the
`this.deferredUpdate.delay(this.updateBuffer);`
was executed, the reload function would be called. But by putting alerts, I discover that this is not the case. reload is called only once as it should be) despite the
alert('Firing reload');
popping up multiple times. I am using a Date Filter for this example.
Why is this so? does not a call to deferredUpdate.delay automatically trigger the reload as per the GridFfilters.js class?
The GridFilter is using Ext's DelayedTask delay method (here) which cancels any pending delayed methods and queues a new one. Hence you are getting multiple alerts, but only one refresh.
Related
In a particular scenario, I need to call the the github api to retrieve a specific user's info. Then issue a second call to retrieve the user's repositories:
search(login: string): void {
this.user = undefined;
// first call
this.githubApi.getUser(login)
.then(user => {
this.user = user;
// second call
this.githubApi.getRepos(user.repos_url)
.then(reposResponse => {
this.repos = reposResponse.repos;
// I don't like to call this.$scope.$apply() !!;
});
});
}
The first call gets executed and the bound elements to this.user gets updated with no problem in the view.
The second call gets executed and the result is returned successfully and this.repos is set correctly. But, the bound elements on the view are not updated.
If I call this.$scope.$apply() in the very last line of the second callback, it makes the view update work but I guess this is not correct approach.
Any solution?
Well, if you are not willing to use $scope.apply();, try updating your getRepos service response code with:
setTimeout(
() => {
this.repos = reposResponse.repos;
}, 0
)
First you need to know , why Angular-Js is not updating the view.
You have used $scope.$apply(), so I'm assuming you already know , how it works and why we use it. Now , to the problem!
Sometimes when you make a callback - nested callback in particular - Angular does not update the view. Sometimes angular thinks that it does not need to update the view because of callbacks. And the watchers do not take action when the value changes of the variable that they are watching.
Then you use $scope.$apply() to run the digest cycle again (assuming you already know the digest cycle if you don't then let me know). And it makes the watchers to update the view.In your case, digest cycle is not running, that is why angular is not updating the view. If your digest cycle was running , angular would have given you error. So, it will tell angular to run digest cycle again because two-way binding is not working properly.
I don't think there is another way. But if there is a way, I would love to know that way. Also its not a bad approach. It was made for these kind of problems.
I'm looking for a pure angularJS way to call a controller method once a particular dom element is rendered. I'm implementing the scenario of a back button tap, so I need to scroll to a particular element once it is rendered. I'm using http://mobileangularui.com/docs/#scrollable.
Update: how my controller looks like:
$scope.item_ready=function(){
return document.getElementById($scope.item_dom_id).length;
};
$scope.$watch('item_ready', function(new_value, old_value, scope){
//run once on page load, and angular.element() is empty as the element is not yet rendered
});
Thanks
One hack that you could do and I emphasize hack here but sometimes it's just what you need is watch the DOM for changes and execute a function when the DOM hasn't changed for 500ms which is accepted as a fair value to say that the DOM has loaded. A code for this would look like the following:
// HACK: run this when the dom hasn't changed for 500ms logic
var broadcast = function () {};
if (document.addEventListener) {
document.addEventListener("DOMSubtreeModified", function (e) {
//If less than 500 milliseconds have passed, the previous broadcast will be cleared.
clearTimeout(broadcast)
broadcast = $window.setTimeout(function () {
//This will only fire after 500 ms have passed with no changes
// run your code here
}, 10)
});
}
Read this post Calling a function when ng-repeat has finished
But don't look at the accepted answer, use the 3rd answer down by #Josep by using a filter to iterate through all your repeat items and call the function once the $last property returns true.
However instead of using $emit, run your function...This way you don't have to rely on $watch. Have used it and works like a charm...
I'm using angular chosen with angularstrap and i'm having problems with the initial value of the selector to be selected. The way i got it to work is i set a Timeout on the model attached to the selector to wait for the dom and then set the model value. So my guess is that chosen needs to wait for the dom to be created before it can initialize the selected option.
$scope.showModal = function() {
myModal.$promise.then(myModal.show);
// hack to make chosen load
$timeout(function () {
myModal.$scope.SelectedColor = "green";
}, 500 );
};
in my opinion this timeout solution is not a good one and i would like to find a better way to set the model after the dom has been created.
This is because chosen directive is calling trigger("chosen:updated") before the DOM is actually loaded. A fix would be adding $timeout() to the $watchCollection trigger.
This has been discussed and looks like the solution is here in the answer from kirliam.
Someone should issue a pull request for this issue.
edit: I issued a pull request for a fix regarding this issue. Hope it gets merged in.
I'm integrating Fine Uploader into an existing workflow. The user needs to provide a bit of metadata and select a file, then click Upload.
The Upload button should be disabled until a file is selected. If the user deletes the file, it should go back to disabled. I have autoUpload:false.
I'm using AngularJS so I'm binding to a function which invokes $("#fine-uploader").fineUploaderS3('getUploads'), and seems like a nice way to handle it.
However, I need a way to get notified when the list has changed, so I can trigger the digest cycle and update the UI. I've tried registering callbacks for the submitted and cancel events, which works – except that cancel is called when the upload is still in the list.
Is there a cleaner way to get a callback when the user adds or removes a file from the list of uploads?
In your case, listening for the "cancel" event is not appropriate. Why? Because the file/upload is not actually cancelled when your cancel callback is invoked due to the fact that you are able to abort the cancel attempt via your callback handler's return value.
You can be sure that the file has been cancelled internally by listening for the statusChange event. When it has truly been cancelled, your statusChange event handler will be called with the file ID and a newStatus parameter of qq.status.CANCELED.
You can read more on status change handling in the docs.
UPDATE: Since you are using Fine Uploader UI, the file is not removed from the UI until just after this status is updated. This doesn't seem like an issue for you though, since you are utilizing the getUploads method to determine file status.
Here's my working solution, in case it's useful to someone else:
$scope.uploader = $('#fine-uploader').fineUploaderS3({
...
}).on('statusChange', function (event, id, oldStatus, newStatus) {
$timeout(function () {
$scope.$digest();
});
});
$scope.has_selected_file = function () {
if (!$scope.uploader) return false;
var uploads = $scope.uploader.fineUploaderS3('getUploads');
var result = _(uploads).some(function (item) {
return item.status !== qq.status.CANCELED;
});
return result;
};
(Uses Underscore.js)
(Follow on questions from Placeholder Hidden)
I'd like my form to validate existing data when it is loaded. I can't seem to get that to happen
I jQuery.each of my controls and call focus() and blur(), is there a better way than this? I tried to call ctrl.checkValidity(), but it wasn't always defined yet. When it was, it still didn't mark the controls.
I seem to have a timing issue too, while the focus and blur() fire, the UI does not update. It's as if the Webshims are not fully loaded yet, even though this fires in the $.webshims.ready event.
I also tried to call $('#form').submit(), but this doesn't fire the events as I expected. The only way I could make that happen was to include an input type='submit'. How can I pragmatically case a form validation like clicking a submit button would?
Here's a jsFiddle that demonstrates the problem. When the form loads, I want the invalid email to be marked as such. If you click the add button it will be marked then, but not when initially loaded. Why?
Focus and blur in the control will cause it to be marked.
BUT, clicking ADD will too (which runs the same method that ran when it was loaded). Why does it work the 2nd time, but not when initially loaded?
updateValidation : function () {
this.$el.find('[placeholder]').each(function (index, ctrl) {
var $ctrl = $(ctrl);
if( $ctrl.val() !== "" && (ctrl.checkValidity && !ctrl.checkValidity()) ) {
// alert('Do validity check!');
$ctrl.focus();
$ctrl.blur();
}
});
}
I see this in FF 17.0.5. The problem is worse in IE9, sometimes taking 2 or 3 clicks of ADD before the fields show in error. However, I get errors on some of the js files I've liked 'due to mime type mismatch'.
This has to do with the fact, that you are trying to reuse the .user-error class, which is a "shim" for the CSS4 :user-error and shouldn't be triggered from script. The user-error scripts are loaded after onload or as soon as a user seems to interact with an invalid from.
From my point of view, you shouldn't use user-error and instead create your own class. You can simply check for validity using the ':invalid' selector:
$(this)[ $(this).is(':invalid') ? 'addClass' : 'removeClass']('invalid-value');
Simply write a function with similar code and bind them to events like change, input and so on and call it on start.
In case you still want to use user-error, you could do the following, but I would not recommend:
$.webshims.polyfill('forms');
//force webshims to load form-validation module as soon as possible
$.webshims.loader.loadList(['form-validation']);
//wait until form-validation is loaded
$.webshims.ready('DOM form-validation', function(){
$('input:invalid')
.filter(function(){
return !!$(this).val();
})
.trigger('refreshvalidityui')
;
});