So I have been plowing the internet to understand or see and example of what I want to do.
It shouldn't be difficult, but something is just missing to me.
The Scenario
I have a search page, built from 2 directives/ ui-views like this:
What I want to achieve
When I press Search, I want to trigger the Search Results directive/ view to fetch the corresponding results based on the search form parameter.
Where I am stuck
Because I have 2 separate directives, I can make them share information using the parent controller, OR the search service I have (to communicate with the backend).
However, The search directive can write information to either one, BUT the results are still not triggered. Unless I actively check for changes every once in a while for changes, I won't get the cling saying I have been triggered.
That is definitely not the the AngularJS way, and I just don't seem to have enough experience to think of something else.
What I am asking you
How would you approach this situation, what will you use to make this page as clean as you can, and modular (of course).
I've had ideas that at the worst case scenario, I will omit the modular approach, and just do it dirty, but working.
Still, this annoys me because as far as I know, this is one of the STRONGEST features of Angular.
I'd appreciate if you could attach some code for all to see and learn
As far as I see, this page is turning around of search functionality. So what I suggest you to implement here - to include search text into your routing parameters.
Your Search box which is help user to write down search query. Make it add search query to routing as some parameter, once user click Search button. It will be the only one responsibility of Search box, to change location URL, literally.
Action: User wrote down Founder in the search box input and pressed button Search.
Result: Location changed from #/search/ to #/search/Founder
The search result view should just respond to the location change. If the search string is changed, it should do all needed calls to the server, and return, process and represent search result in the Search result block.
Related
I have some data on a model that comes in the form of a code such as "US60" and "US70".
I need to take that value and show a display value such as "US 7day/60hour" and "US 8day/70hour". I'm not sure if there is any best practices way to do this in Angular, and I'm not having much luck googling it.
What I would do is have a service that I pass in type and value, and it would return a display value, but as with many things in Angular, since this is my first Angular project, I don't know if it's a good way to do it or not.
I'm just needing to use the display value in html such as {{settings.cycle}} I am already able to access the variable, but I want to show the display value, not the actual value.
If I am getting the gist of your question correctly, you have the value available but want to alter how it is displayed on screen right?
There are two main approaches to do this in Angular, using a directive or a filter.
A filter is basically like a pipe in Unix. You can alter a value before it is being displayed. For example:
{ username | uppercase } will transform the username into an all-caps username. Naturally, you can define your own filters for your use case. Filters are mostly used to transform single values. So for your case, a filter sounds best.
A directive is commonly used to create entire components on a page. For example: <user-profile-card></user-profile-card> would be transformed, using the directive, into the appropriate html/css/logic. So these are used often for larger transformations which involve logic, like server requests. Still these directives could also be used for very small components.
So for your case, although what you are actually want to do is not completely clear to me honestly, a filter seems to be your best shot ;)
Many examples on the net show you how to use ng-repeat with in-memory data, but in my case I have long table with infinite scroll that gets data by sending requests to a REST API (scroll down - fetch some data, scroll down again - fetch some more data, etc.). It does work, but I'm wondering how can I integrate that with filters?
Right now I have to call a specific method of API service that makes a request based on text in "search" input box and then controller updates $scope.data.
Is it possible to build a custom filter that would do that? And then my view would be utterly decoupled from the service and I could declaratively tell it how to group and order and filter data, regardless if it's in-memory or comes from a remote server, server that can serve only limited records at a time.
Also later I'm gonna need grouping and ordering as well, I'm so tempted to download the entire dataset and lock parts of the app responsible for grouping, searching and ordering (until all data is on the client), but:
a) that dataset is huge (hundred thousands of records)
b) nobody wants to deal with cache invalidation headaches
c) doing so feels so damn wrong, you don't really expect me to 'keep' all that data in-memory, right?
Can you guys point me to maybe some open-source examples where I can steal some ideas from?
Basically I need to build a service and filters that let me to work with my "pageable" data that comes from api, like it's in memory-data.
Regardless of how you choose to solve it (there are many ways to infinite-scroll with angular, here is one: http://binarymuse.github.io/ngInfiniteScroll/), at its latest current beta version, ng-repeat works really bad with large amount of data - so do filters. The reason is obvious - pulling so much information for changes is a tuff job. Moreover, ng-repeat by default will re-draw your complete list every time something changes.
There are many solutions you can explore in this area, here are the ones I found productive:
http://kamilkp.github.io/angular-vs-repeat/#?tab=8
http://www.williambrownstreet.net/blog/2013/07/angularjs-my-solution-to-the-ng-repeat-performance-problem/
https://github.com/allaud/quick-ng-repeat
You should also consider the following, which really helps with large amounts of data.
https://github.com/Pasvaz/bindonce
Updated
I guess you can't really control your server output, because filtering and ordering large amount of data are better off done on the server side.
I was pointing out the links above since even if you write your own filters (and order-bys), which is quite simple to do - http://jsfiddle.net/gdefpfqL/ - (filter by some company name and then click the "Add More" button - to add more items). ordering by is virtually impossible if you can't control the data coming for the server - the only option is getting it all, ordering and then lazy load from the client's memory. So if each of your list items doesn't have many binding by it self (as in the example I've added) - the list item is a fairly simple one (for instance: you simply present the results as a plain text in a <li>{{item.name}}</li> then angular ng-repeat might work for you. In this case, filters will work as expected - say you filter by searched text:
<li ng-repeat="item in items | filter:searchedText"></li>
even for new items added after the user has searched a text, it will still works because the magic of binding.
my premise was wrong. while AngularJS was certainly slowing things down, it was not due to the problem I describe below. however, it was flim's answer to my question - how to exclude an element from an Angular scope - that was able to prove this.
I'm building a site that generates graphs using d3+Raphael from AJAX-fetched data. this results in a LOT of SVG or VML elements in the DOM, depending on what type of chart the user chooses to render (pie has few, line and stacked bar have many, for example).
I'm running into a problem where entering text into text fields controlled by AngularJS brings Firefox to a crawl. I type a few characters, then wait 2-3 seconds for them to suddenly appear, then type a few more, etc. (Chrome seems to handle this a bit better.)
when there is no graph on the page (the user has not provided enough data for one to be generated), editing the contents of these text fields is fine. I assume AngularJS is having trouble when it tries to update the DOM and there's hundreds SVG or VML elements it has to look through.
the graph, however, contains nothing that AngularJS need worry itself with. (there are, however, UI elements both before and after the graph that it DOES need to pay attention to.)
I can think of two solutions:
put the graph's DIV outside the AngularJS controller, and use CSS to position it where it's actually wanted
tell AngularJS - somehow - to nevermind the graph's DIV; to skip it over when keeping the view and model in-sync
the second option seems preferable to me, since it keeps the document layout sane/semantic. is there any way to do this? (or some, even-better solution I have not thought of?)
Have you tried ng-non-bindable? http://docs.angularjs.org/api/ng.directive:ngNonBindable
<ANY ng-non-bindable>
...
</ANY>
I would like to format my URL like so:
/teacher/page:2
to
/teacher
I would like to achieve this result by using as less code as possible (perhaps only from routes.php?), without modifying how the PaginatorHelper behaves.
Thank you for your help!
You can accomplish this with:
ajax
form posts instead of gets (requires altering the pagination
helper)
But I would advise against it. This is designed for good usability. If you change it, It will make your site less user friendly than you may want it to be. I know I would be frustrated trying to jump to a specific page only to find out I have to click my way to page 35. Yuck!
suppose user navigated to silverlight page at root/myurl. When user presses f5 I would like the browser to fetch the content of root/, not root/myurl. Is this possible to accomplish?
What I would do is write a flag to your local storage that says, in effect, "'root/myurl' is the last URL I visited." And when when someone reloads "root/myurl", check to see if that flag exists. If it does, renavigate to "root/". It's a little complex, but something of that sort ought to work.
The other approach I usually take in these instances, where I find myself wanting behavior that doesn't match how the browser normally behaves, is to figure out why I'm doing things different from everyone else. Quite often (almost always), there's a better and more natural way to do it, if I'll just take a step back and figure out what I'm really wanting.