Question Background:
I'm learning AngularJS. I have created a simple app that takes in 3 form inputs, and on submission of this form a paginated list should be rendered. I have a dependancy on UI-Bootstrap. This is a Plnkr showing the pagination example I'm attempting to incorporate into my app: http://plnkr.co/edit/81fPZxpnOQnIHQgp957q?p=preview
The Issue & Demo:
This is the link to my code so far on CodePen:
http://codepen.io/daveharris/pen/NNMQyy
I have a list of 1000 items populating on my SearchingService model that is injected and shared between the two controllers.
I cannot get the paginated ng-repeat to populate when the searchingService.searchList list on the SearchingService model is changed,
It is as if the $scope.Watch is not being triggered.
Any help getting to the bottom of this will be much appreciated.
Change line 31 from $watch to $watchCollection. Since your service is mutating the array (via .push), the reference stays the same, so the $watch won't trigger. $watchCollection will watch references to the array members rather than the reference to the array itself.
As bchemy pointed out, $watch should be changed to $watchCollection. But this change won't be enough to have your app working correctly with your current code, since the pagination looks broken.
You should also add another watcher to control the pagination as the one in the example that you want to replicate:
$scope.$watch('currentPage + numPerPage', function() {
var begin = (($scope.currentPage - 1) * $scope.numPerPage)
, end = begin + $scope.numPerPage;
$scope.filteredItems = $scope.searchingService.searchList.slice(begin, end);
});
Also $scope.items array was getting duplicate searchLists in it and would mess the pagination length.
I have created this Plunker where you can see your example fully working.
Related
I have started a demo app and come across this problem where my parts that I am adding to the repairs are not being properly proccessed. This is my first angular that I am building.
To get the bug press update on one of the repair cards and then scroll down to the quantity and repair item section at the bottom of the form and try to add a new item. it doesnt regester what is in the form.
This is the codepen with the full view that doesnt work.
This is the function in the controller to pass the info the factory.
$scope.addPartsPerRepair = function() {
partFactory.addPartsPerRepair($scope.newPartsPerRepair);
$scope.newPartsPerRepair = {};
};
This is the function in the factory to add the new repair to the array partsPerRepair
factory.addPartsPerRepair = function(newPartsPerRepair) {
partsPerRepairs.push(newPartsPerRepair);
};
After I abstracted away the repair factory and simplified my view we are left with this
This is the codepen with the partial view that does work.
I have been over this code for the past 6 hours trying to fix this one probelm and I can not see my issue.
Secondly, This is more of an add-on question, Does anyone have any advice on how to save the partsPerRepair to the actual repair[Idx] instead of in one array called partsPerRepair that every repair accesses. I thought I might be able to add an array called parts to each repair and store quanity and item name in that array but that has proven to be more difficult then I can manage. I realize I am asking two different questions but since your here reading I figured you might be willing.
Thanks in advance for any help.
An updated CodePen.
So I've tried to resolve both your questions here, but all I have edited is the arra yof repairs and the add parts method, which means there is alot of cleaning up chanegs to be made like deleting the old partsPerRepairs and its references.
First thing newPartsPerRepair needed to be intialized this is why add parts was not working the function was passsing undefined(anything used as model in ng-model needs to be intialized), which is done in the controller - $scope.newPartsPerRepair = {};.
Second I moved the partsPerRepairs array into the repairs array and called it parts this is under each customer in the array, this is to answer your second question.
Third I changed the way the ng-repeats work to use these new parts arrays - ng-repeat="partsPerRepair in repairs[$index].parts track by $index"
Finally I moved and edited the addNewParts to the repairs factory so it used the new parts array and could access the repairs array.
Hope this all helps.
I'm working with Angular and part of my page utilizes ng-repeat to display some bug tracker tickets. As part of the site, I also want to provide the ability to search tickets. I'm able to get that part working as I want, and if I'm just appending new tickets they show up fine.
However I would like to be able to, if a user searches, delete all of the currently visible ticket divs and replace them with the search results.
My initial thinking, since I have the ng-repeat set as item in tickets track by item.id, was to just set $scope.tickets equal to the new data. However, this didn't cause Angular to update the DOM.
So, I tried setting $scope.tickets equal to an empty array and then setting it equal to the new data:
$scope.$apply(function() {
$scope.tickets = [];
$scope.tickets = data;
});
Still no update to the DOM, even though console.log($scope.tickets) shows the correct objects.
I'm aware of the method of
$scope.$apply(function() {
array.splice(index, 1);
});
to remove individual elements, but I'm not sure how I would apply that removing all of the elements.
I'll try and get a Plunkr or JSBin added to the Q soon.
What would be the proper way for me to make Angular replace all of the current elements with the new elements created from the data?
try setting array.length = 0
this deletes all elements, while not removing the reference to the array, which actually seems to be the problem in your case.
but another way would be to have a additional data bag.
for example have $scope.data.tickets then you can reasign tickets as usual. important thing is, you have to reference your items using item in data.tickets
Did you test $watch?
$scope.$watch('tickets', function() {
// update data HERE
});
Fiddle:
https://jsfiddle.net/fierflash/0h6uL4ek/2/
Objective:
When a re-order takes place(through Sortable), send a AJAX Request to backend to save the new positions of the tasks
Whats v-sortable?
http://am2studio.hr/blog/creating-dynamic-table-with-vue-js/
Problem
The markup is updated but the model is not updated. In this case the value of task.position remains the same when a re-order takes place.
How should the $watch look like for this(if needed)? What values should I put in?
How to solve this?
The main problem you are running into with that approach is you are trying to update the position by using an input with type="hidden". Vue's v-model does not support that input type (and unfortunately doesn't emit an error message in that case either).
Since you are just trying to update the position after the drop ends, why not just walk the array and set it afterwards like this?
that.value.forEach(function (task, index) {
task.position = index + 1;
});
Working fiddle here: https://jsfiddle.net/zuwg1dh6/1/
I am relatively newer with Angular so please excuse my mistakes, if any. I have to modify and use this treeview directive from NgModules. It's code looks promising but I have to modify it a little bit to add the functionality of add/ delete or modify items.
Plunker
I was previously using jQuery to create my treeview and have accomplished all the relevant tasks. But since I decided to shift to Angular, I have to do it the angular way.
So as far as I could understand this directive uses nested recursive directive to create the tree, which is an efficient way to do it. It works fine, but I would have some 3000-4000 items to show in my treeview. So when I do that with this code it slows down the screen and consumes much memory due to the many watch expressions (5-7 per item).
Plunker
I have tried one time binding in ng-repeat with :: notation. That has helped a lot but now I couldn't implement my add or update methods. Is there any way I could accomplish this?
<li data-ng-repeat="node in ::' + treeModel + '">
https://plnkr.co/edit/KwnvyslibWd1dmIXxBYU?p=preview
You already had the selected node in the scope, so simply push the new node into it's children array.
$scope.AddNode = function(NewNode)
{
NewNode = {"roleName" : NewNode , "roleId" : "role11", "children" : []};
$scope.mytree.currentNode.children.push(NewNode);
};
edit: As name suggest - it is one time binding, so adding/removing won't work here. I think it's only normal that browser get's a bit stuck when trying to display such amount of data once. Instead, you could add nodes by bits, say 20 a step. Or you could check out other libraries as well. This one gives you the option to display array of nodes collapsed at first.
I have made an AngularJS directive that requires a model and converts the value of the model (which, in this example is "25mm") to something else that is showed in the view (in this example, converted to inches).
Here is a working plnkr demo: http://plnkr.co/edit/fO1S9GcubHE57Pf7Kt9G?p=preview
The demo, however, doesn't work as expected. After changing the value of the dropdown from "inches" to "feet", I'd expect the view to be re-rendered with the appropriate value. This is not the case.
I have noticed that this is because I'm not "listening" for changes, and that is why I placed the
scope.$watch("[convertFrom, convertTo]", function(n) {
});
which works fine in terms of watching for changes, but if I uncomment that $watch, the formatter stops working.
My second problem is that I'm pushing functions to the arrays $formatters and $parsers. To be exact, one function every time the value of the dropdown changes.
My questions are:
How can I watch for changes and make the formatter work?
How can I not insert a new function in the $formatter and the $parser arrays every time my dropdown changes.
I managed to do it myself. Here is a plunkr demo: http://plnkr.co/edit/jgF2QIP4QeA0Glcnn35B?p=preview
It turns out that I need to push my $parser and $formatter function only once and watch for changes from outside, then trigger a "re-parse" or "re-format":
scope.$watch("[convertFrom, convertTo]", function(n) {
ngModel.$modelValue = '';
});