I'm having to move a project from rails to angular, Much to my disgrace.
How would i go about changing this
<% if souporder.datefrom > Time.now %>
into angular terms?
heres my code
<tr ng-repeat="soup in souporders">
<td>{{soup.id}}</td>
<td>{{soup.soup}}</td>
<td>{{soup.datefrom}}</td>
<td>{{soup.dateto}}</td>
</tr>
Edit
This is in my view
<div ng-repeat="soup in souporders">
<tr ng-if="date == soup.datefrom">
And this is in my controller
$scope.date = new Date();
You clarified in the comments that you only need this calculated on page refresh, which is pretty simple and doesn't require much angular magic.
On initializing the view's controller, simply set a variable whether or not the order date is in the future or not and expose it on the scope. Then bind directly to it, and use the bindonce functionality {{:myvariable}} to improve performance because it won't be changing anyway.
Depending on your needs, you can even have the server calculate that value and return it as a property of each order in your JSON array of orders. (I'm guessing a bit at what you're doing, but you can adapt the answer if you're not doing what I think you're doing.)
Update: I just realized that perhaps your objective is not to do something special with each row based on the date, but to filter the list based on the date. Most of my answer still stands, but you can forget about the bindonce spiel. What you need is called an angular filter on ng-repeat and is done using the pipe (|) character. You can read all about it by searching the topic. There are examples in the angularjs docs. But basically, instead of:
<tr ng-repeat="soup in souporders">
<td>{{soup.id}}</td>
<td>{{soup.soup}}</td>
<td>{{soup.datefrom}}</td>
<td>{{soup.dateto}}</td>
<td>{{:soup.active}}</> <!--do something nice here instead of just displaying true/false --->
</tr>
You might want:
<tr ng-repeat="soup in souporders | filter:{current: true}">
...etc
</tr>
Either on the server or on the client, when you load the data from the server, you can add a boolean property to the items in the souporders array that says whether it's current or not.
What this accomplishes:
You have a filtered list of items based on a property that does NOT change dynamically and requires a page reload to update. But it's fast (but not the fastest it could be if you really need to go crazy - don't prematurely optimize, you'll know what to do when the time comes to do it, and that time isn't now).
Why it's not that great:
It isn't dynamic and it isn't angular-y or declarative. But based on your requirements, it's a solution. I'd spend some time considering if you want this to be dynamic, and if not, why the items that aren't showing are even returned from the server. Are they used elsewhere on the page?
Related
I finally managed to make my date filters work but now I have a problem...
I have a simple table that is supposed to be filtered by name and date. It is filtering correctly but the date filter is extremely slow. After debugging and researching I know the problem is that my custom dates range (from - to) filter is called many times.
It is called:
When I click on the calendar to choose a date but before actually showing the calendar control
Right after showing the calendar
After selecting a date
It even runs the first 2 times if I don't chose any date after opening the calendar. It also runs every time I change from one month to another.
Also, for each of those 3 times the filter is called, it also runs once for each row I have in the list. In the example I have only 10 rows (it is actually fast) but in my application it has maaany more and it takes a long time.
The ideal is that this code gets called only once after selecting a date.
For simplicity I'm showing here a few lines of my code, but you can see the whole example on this Plunker :
HTML Code:
<!-- This is the datepicker control filter -->
<ng-datepicker ng-model="DateRegisteredFrom" view-format="MM/DD/YYYY" placeholder="mm/dd/yyyy"></ng-datepicker>
<!-- Here is the table -->
<tr ng-repeat="item in model.People | filter:searchText | dateRegisteredFilter:DateRegisteredFrom:DateRegisteredTo | orderBy:orderByField:reverseSort ">
</tr>
And this is my javascript code:
.filter("dateRegisteredFilter", function($filter, $rootScope) {
return function(items, from, to) {
return $filter('filter')(items, "DateRegistered", function(v) {
// Filter code...
});
};
});
After a lot of reading and researching I learned 2 things:
My code gets called this many times due to "dirty checking" done by angular (I read it thanks to this answer: ng-repeat execute many times )
The actual comparision of dates is slow (this would be ok if the code was executed only once but not many)
I would appreciate a lot if somebody could point me on the right direction or if I'm doing something wrong as I've been reading and I only find the reason why this happens but I can't find a solution or a suggestion.
I think you need to change how you are handling your ng-repeat. As you are aware, these filters is constantly running, and because of that it is causing things to run slowly. What you should do is transform the data in model.People separately in your controller instead of piping it through multiple filters. Doing it that way, you can better control when and where the filtering gets done.
This link has a cool gif that helps to show why things are so slow as well https://medium.com/#lightingbeetle/some-best-practices-when-building-a-large-angular-application-c346734a4e9c
is there a way to query a MongoDB collection, return the results, use an AngularJS ng-repeat to iterate through the results, BUT BEGIN the iteration at a specific position in the results, somewhere in the middle for example?
I am currently returning a query to an angular view; a category of materials. Then i have my view set up to paginate(ng-repeat) through the results. However, no matter what material I click on to bring me into the view (from a different view), the ng-repeat always starts at the beginning of the materials list, rather than on the material i clicked. Any thoughts?
I do not believe the mongodb part has anything to do with the actual question but ill give you 2 options:
The quick way:
<div ng-repeat="item in items" ng-show="$index >= myCtrl.startPoint">
While this will do the trick you might want to do the ng-show expression with a filter. In addition you might run into performance issues. You should also use the track by feature.
A better way would be to have a filteredData model for the ng-repeat and do the correct filtering once per action. You would have to make sure yourself that the model is updated on every data change and every user input.
There are many choices in between these 2 options but what to use depends on your needs. For instance - does user input change frequently? Is your data updated frequently? etc.
I'm new to Angular and am implementing something that requires a large ng-repeat loop. Of all the things in the loop I'm only showing one however. I show it using ng-if (ng-if over ng-show so as to remove all other elements from the DOM). My question is: if I have considerable amounts of data inside the elements whos ng-if statements don't evaluate to true, for example some images or very big tables, is that data still downloaded by a user accessing the page with the ng-repeat and ng-if statements on? I.e If I had my ng-repeat repeating 10 times and each time generating a div containing a 100,000 row table, even though only one of the tables shown via the use of ng-if, are all of the other tables evaluated and so downloaded by the user? This is in the interest of bandwidth.
I hope that made sense. For illustration purposes here's an example
<div ng-repeat="foo in bars">
<div ng-if="foo.property == 1">
{{ foo.veryBigTable }}
</div>
</div>
You are actually mixing two parts of a web application i.e. your server side code and your client side angular code.
The answer to your question is Yes, i.e. the whole data will be downloaded from server irrespective of your ng-if condition.
Since you will be populating your data in scope element bars somewhere in your code which will contain all data returned from server and server does not know the conditional data you implemented in the HTML. Its up to the HTML code to display the displayable data based on ng-if condition.
So you need to modify your server code to only send that amount of data which is going to be displayed. This is the way you can save your bandwidth.
Hope, you got my point!
A sample application is at: http://jsfiddle.net/qvkyrg7k/8/, why do I get $rootScope:infdig?
Basically I'm trying to take an array of items, filter by a search term and then group based on a property so I can show in a tree like way.
The problematic line is
<tr ng-repeat-start="(family, members) in data | filter:search | groupByFamily">
See https://github.com/angular/angular.js/issues/10738 for the reason and track. Basically, ngRepeat watches the result of the pipe using $watchCollection. Since groupByFamily creates new arrays each time it is run, angular thinks the whole model changed and triggers a rerender which then makes groupByFamily run again, etc.
On the Cognos Report Results Page, we need to have a checkbox for each row.
The checkbox is designed using HTMLITEM tag.
However, the problem we face is that the state of the checkbox (checked or unchecked) is not persisted when we go to the next page/previous page.
I am very new to Cognos and I need to know if there is a way to do this.
I am fairly good at JAVAScripting and JSP, but since we only have access to HTML elements and not JSP Tags (Cognos uses CGI anyways), I cannot get the request object.
If there is some way to retrieve the request objects parameters of previous submit(previous page), that would help in solving the issue to a large extent, I feel.
Jonas
There isn't really enough information on what your end goal is to be able to assist you with this properly. There are a few ways that spring to mind that would allow you to use JS on the report to remember previously checked items, but there may be a much better way to do this depending on your requirements.
Without having more details, the first thing that leaps to mind is simply having some JavaScript set and unset cookie values on check/uncheck on the checkbox.
Note, there could be a variety of other ways to work this, including upping the number of visible rows per page, etc...
You can create a dataitem in a query where you can determine whether your checkbox should be checked or not. In the design of your list on the report page you can render a HTMLItem within the list, and base the HTMLItem on a DataItem. Your HTML must than be something like
<input type="checkbox" value="""+ [DataItemValueToPass] + """ " + [DataItemCheckedOrNot] ></input>