ng-change not working after first upload - angularjs

http://embed.plnkr.co/keaGc3Y4Pmgfs04HJgnC/
Here is the link of my code.I am trying to validate my upload by disabling the load data button when the file is empty.
It is working for the first time,but when the next time I upload the file,ng-change is not working and the button is still showing disabled although I have uploaded the next file.
I am a beginner in AngularJS,so i might be doing some basic mistake.please help.

Since you are trying to upload the same file again, the onChange event will not fire, because it is the same file. To resolve this issue, you need to unset the input field after you uploaded the file. Unfortunately, you have to use jQuery (or get the element wit vanilla js) for this. So, in your onFileLoad function you could do something like this:
angular.element("input[type='file']").val(null); // Unset Input
$scope.filename = undefined; // Unset $scope property
Note that this is not the "angular" way of doing this. It would be better to move this into a directive, cause you should not manipulate the DOM within a Controller.
Update:
As said before, you need to include jQuery for this to work. Angular's jqLite does not support selecting DOM elements by its type. So, either you include jQuery (needs to be loaded before angular!) or you modify the code so you can use vanilla JS or jqlite.

Please change, initially
vm.foo = 'Monthly'
<input type="radio" name="{{item.deviceId}}" ng-model="renew.foo" ng-value="'Monthly'" ng-click="renew.updatePref(item, 'Monthly')">Monthly
<input type="radio" name="{{item.deviceId}}" ng-model="renew.bar" ng-value="'Yearly'" ng-click="renew.updatePref(item, 'Yearly')">Yearly
you have use ng-change, change event never happen as value for these input remains always same. use,
var vm = this;
you are also using ng-value="Monthly", Monthly is variable (undefiend) for ng-value. either use value="Monthly" or ng-value="'Monthly'".

Related

How to find and replace a specific text on a page

How to find and replace a specific text on a html page using AngularJs
That text is on a third party component so the id and the class is keeping changing. What I can reference is the text itself that I want to change.
That specific text on the html page is no class or id or any ng-tag around it.
I am not a angularjs developer and the page was built on asp.net mvc with the view (cshtml) using angularjs version1.
Is there a way in angularjs to find and place the text like the way in javascript:
document.body.innerHTML = document.body.innerHTML.replace('old_text', 'new_text');
Thank you!
In angularjs each application state(page) has a controller. The logic to access the Dom should placed in said controller.
To manipulate the DOM please see this answer
In Angular world, it's called data binding. Here are the official docs on data binding.
Here is the working DEMO of data being updated in time. First, html displays "Initial Text" and in 5 seconds it's changed to "New Text".
What was done for this demo:
An angular component was created with a dedicated variable $scope.text that holds text values that will change in time.
Then, this variable is used in the HTML markup, like this: {{ text }}.
Angular handles the HTML re-rendering automatically for you, so when the value of $scope.text is modified in the component, Angular forces re-rendering of the html in the browser
UPD another example with Angular two-way binding: DEMO.
Here user can change $scope.text value in the input field, which automatically changes its value in the controller. Try to edit the input field and you will see how it instantly updates in the header above the input field.

How to clear the md-autocomplete cache?

I'm using md-autocomplete to show results of an api query. Attribute md-items is iterating over a promise: item in getItems(searchText).
This is working well, and using the cache subsequent uses of the same search text return immediately with the same results.
But I need to be able to clear the cache at some points, when other search parameters change. How can I do this? By accessing the md-autocomplete controller perhaps? Although that seems non-standard and I'm not sure how.
As of version 1.0.5 of angular-material this isn't possible. I didn't find any acceptable workarounds, so I'm just disabling the cache with md-no-cache="true".
I've logged an issue for this on the angular-material project including a suggestion on how it could work.
It is definitely possible to reset the md-no-cache attribute programmatically anytime on your md-autocomplete directive.
If you have a boolean variable on your controller, let's say:
$scope.noCacheResults = false;
Then on your directive you can bind this variable to the md-no-cache attribute:
<md-autocomplete ...
md-no-cache="noCacheResults">
</md-autocomplete>
Like this, whenever your search parameters change you can set the $scope.noCacheResults to true or false depending whether you want to keep caching the query results or not.
Something that worked for me. Put an ng-if on your autocomplete. Then, in the code that changes the value of the other fields affecting this field, set that value to false, and then within a timeout, set it to true again. This will effectively remove the item from the DOM and put it back all nice and new with no cache.

ui-bootstrap pagination with filter

after some research and study of examples I implemented a pagniation with a filter function.
Im very new to angular, so I need your help if this application is ok or it has some bugs/logical errors.
The target is to select a collection (in this application load1 or load2) and create new objects, manipulate existing, or delete some of them. On every update of the data, it has to be checked if the pagination is synchronous to the collection size.
If the user enters something into the search field, a watcher in the controller is fired for updating the filtered data:
$scope.$watch('search.name', function (newVal, oldVal) {
$scope.filtered = filterFilter($scope.items, {name: newVal});
}, true);
I would be very happy if some of you angular pros can look into this code and give me some feedback. I want to use this in a productive system, so every answer would be great!
Here is a working plunkr: http://plnkr.co/edit/j9DVahEm7y1j5MfsRk1F?p=preview
Thank you!
Watchers are heavy if you use them explicitly throughout your large application.
Use ng-change instead. Also, by passing true to that watcher means you're deep watching which is really a bad thing to do, since it will check each property of the object in the array which is performance intensive.
Since I can't see that you need old and new value for a reason, you can simply use $scope.search.name. Whenever you type in something, $scope.search.name has the updated value. Just need to call a function on ng-change.
DEMO: http://plnkr.co/edit/TWjEoM3oPdfrHfcru7LH?p=preview
Remove watch and use:
$scope.updateSearch = function () {
$scope.filtered = filterFilter($scope.items, {name: $scope.search.name});
};
In HTML:
<label>Search:</label> <input type="text" ng-model="search.name" placeholder="Search" ng-change="updateSearch()" />
Previous answer is still the correct, but you will have to make sure to replace the "page" inside the pagination tag and change it to ng-model.
From the changelog (https://github.com/angular-ui/bootstrap/blob/master/CHANGELOG.md)
Since 0.11.0:
Both pagination and pager are now integrated with ngModelController.
page is replaced from ng-model.

how to always use a 'set-method' to change the property of an object used as ng-model

in the controller I have:
$scope.foo = new Foo('test'); // foo.property now 'test'
in the view I have
<input type="text" ng-model="foo.property" />
But I don't really want foo.property to be changed directly.
I want it to be changed by calling a 'set method' for it, like
foo.setProperty('new-value');
So I know I could do something with watch like so:
$scope.$watch('myObject.property', function(newValue,oldValue) {
myObject.setProperty(newValue);
}
But I'll have this situation many times over again, so my question is if I can do this more automatically for every Foo?
or: How can I best implement something in Angular so that every time someFoo.property is used as a ng-model it is changed by calling someFoo.setProperty(newValue)?
You can call the setter method on blur event:
<input type type="text" ng-model="data.property" ng-blur="foo.setProperty(data.property)">
or use ng-change="foo.setProperty(data.property)"
You basically want the foo.property model to not be changed due to User Interaction, yes? Why don't you disable the input box using HTML, which will make sure no user interaction ever changes the input value, and then use $watch? $watch is the perfect way to handle what you require. And as long as it is not a deep watch, there's no performance concern either.

Image crop with AngularJS

I want to let the user crop an image, I found this JQuery plugin - http://deepliquid.com/content/Jcrop.html
I tried to use it with Angular-ui's Jquery passthrough option, adding the ui-jq=Jcrop directive to the <img>
The problem is that If I use ng-src to dynamically change the image it doesn't work and nothing is seen. If I change it to src and put a static url I can see the image and Jcrop.
how can I fix that ?
also, how can I listen to Jcrop's callbacks to know what is the user's selection ?
is there a better / simpler way to add image cropping functionality to AngularJS ?
Here is my solution:
I've written a directive that create img element and apply plugin on it. When src is changed, this img is removed and content that was created by plugin is also destroyed and then re-created new img with new src and again applied plugin on it.
Also provided 'selected' callback to be able to get coordinated that were selected (wrapped in $apply so you can modify your scope values in it).
Check my solution at Plunker
I've built a demo using AngularJS and Jcrop here:
Demo: https://coolaj86.github.com/angular-image-crop
On Github: https://github.com/coolaj86/angular-image-crop
You can leverage ui-event to create an event definition object with the keys being the event names and the values being the callbacks. Or you can simply pass these events as options to Jcrop (according to the documentation)
Finally, there is a new update coming to ui-jq that lets you add ui-refresh which is an expression to be watched to re-trigger the plugin.
Theoretically you should be able to do
<img ui-jq="Jcrop"
ui-options="{onSelect:myCallback}"
ui-event="{onChange:'myCallback($event)'}"
ui-refresh="imgSrc"
ng-src="imgSrc" />
Note: this simply re-fires the passthrough again, and doesn't automatically mean this will fix the problem or that the plugin will behave properly when re-initialized
We're still working on a good way to allow you to trigger different events at different times.

Resources