RESTful routing to single firebase object from firebase array - angularjs

I am confused on how to do a very, very trivial pattern with angular/firebase using angularfire.
Imagine you have a lil' old blog. You have some $scope.posts and you ng-repeat over them. Now you want to be able to click on one post and be routed to that post's page at '/posts/:id'. Since a $firebaseArray elements don't include their $id's how do you pass a unique id of a single post to the url and onto the postsCtrl?
<a ng-repeat="post in posts href="/posts/{{??????}}">{{post.title}}</a>
Update
The workaround I figured out is whenever I save a new post, I can save an attribute called "key" and then use this the way I would normally use the "id" attribute in every other framework.
$firebaseArray(postsRef).$add($scope.post).then(function(ref) {
ref.update({ key: ref.key()});
});
This hack, however, cannot be the solution to this simple, trivial, conventional pattern.
Thanks for any help.

You're instincts are right, that hack isn't the answer. Instead use angular's built in (key, value) option for ng-repeat:
<div ng-repeat="(id, post) in posts">
<a ng-href="/posts/{{post.id}}">{{post.title}}</a>
</div>
Additional reference material on how to use AngularFire with ng1 can be observed in this repo

Related

AngularJS ui-router - Generated <href="">returns current url

I'm new to angularjs and have been scouring for an answer to this problem but to no luck I can't find one.I know that angular (1.x) is older but I still wanted to learn this anyway.
Moving on, I'm trying to dynamically generate links based on a $scope.menu_item object inside a controller of my module. For example if
$scope.menu_items = ['Home','Profile','Settings']
the values in the array correspond to child states of parent state User and is configured using $stateProvider.state()
$stateProvider
.state('user'{
url:'/user',
abstract:true,
templateUrl:'someTemplateThatSeemsToWork',
controller:'MenuCtrl'})
//these are the child states
.state('user.Home',{
url:'/home',
template:'<p>Home</p>' (this is loaded in the template of its parent)
})
.state('user.Profile',{
url:'/profile',
template:'<p>Profile</p>'
})
.state('user.Settings',{
url:'/settings',
template:'<p>Settings</p>'
})
then this in the template using ng-repeat:
<li ng-repeat="menu_item in menu_items">
<a ui-state="user.{{menu_item}}">{{menu_item}}</a>
</li>
As expected, it renders the view properly, the values from $scope.menu_items are properly made into links but the href="" attribute of the tag is equal to the current url.
The default state is 'user.Home' and as such /user redirects to /user/home
(localhost:[port]/user/home)
<a ui-state="user.Home" class="ng-binding" href="/user/home">Home</a>
...
<a ui-state="user.Profile" class="ng-binding" href="/user/home">Profile</a>
...
<a ui-state="user.Settings" class="ng-binding" href="/user/home">Settings</a>
Here we see that all of the generated tags have the href value set to the current url (localhost:[port]/user/profile will make it into href="/user/profile")
So is there anything that I'm forgetting to do? From my understanding, it should work when I use ui-state since it can handle $scope properties.
Some additional notes:
1.) Manually typing the specified state url in the address bar works just fine and renders the correct template
2.) I am using Express to handle the server-side
3.) I set $locationProvider.html5Mode(true)
Temporary Work-around
For the people who might stumble upon this question, I temporarily used a work-around solution and just removed ui-sref="" or ui-state="" and just used
ng-href={{state.url}}
with
ng-repeat= "state in states"
where
states = [{name="stateName", url="/relativeToRootUrl"},{..more States}]
I'd still appreciate a solution for this using ui-sref since it utilized ui-router more.

Add attributes to elements in ng-repeat

I have a
<div ng-repeat="post in getServerPosts()" >
where i ng-bind post.title and post.excerpt. Posts also have unique a post.id but it is not shown (which is what I want since I don't bind it).
I am trying to find a way to allow the user to mark a post by somehow utilizing the post.id. That way, if a user marks a post it will automatically be marked next time the ng-repeat runs (every time the page loads).
I have played around with scopes in the controller but I can't figure out how to handle the post.id this way.
Question is probably beyond newbie level and maybe there are smarter ways to do this. Any hint or advice?

ng-click not working inside ng-switch

I'm beginner with AngularJs, and i have a lot of questions :/
Here's one of them :
I have links that i use to filter data. So when i click on link one, the value for the filter myFilter is one, etc.
Just to show you that my filters work, i putted two times the links (see here http://plnkr.co/edit/2G6mahkmyIixMJ1mEVKp?p=preview)
In the above links, i use ng-swich, cause i want, when i click on a link, to remove the link and only keep the text
In the bottom links, there are no ng-swich, so myFilter works perfectly
Is it possible, to make the ng-click inside the ng-swich work ?
The way you are approaching the issue involves far too much code duplication.
Also it is a bad practice to replace objects directly in the html. If you use a function bound to the scope it is cleaner and you won't run into child scope issues as much
Rather than creating four <ul> you could simply use ng-if within each <li> and use only one <ul>. This would also be a good case to create a very simple directive
HTML
<li>
<span ng-if="myFilter.trimestre==1">Avril - juin</span>
<a ng-if="myFilter.trimestre!=1" ng-click="updateFilter('trimestre',1)" href="#">Avril - juin</a>
</li>
JS
$scope.myFilter={};
$scope.updateFilter = function(key, val){
$scope.myFilter[key]=val;
}
DEMO

ngSanitize does not allow allow id attribute

I am using ngBindHtml to display some HTML from an (internal) CMS:
<span ng-bind-html="cmsHtml"></span>
The HTML contains a link with an id attribute:
"<a id='fsgPdfLink' href='http://blah/download.pdf' target='_blank'>Click here to download the PDF</a>"
However, I notice that the id attribute is removed by angular before writing the link to the page, so what gets rendered is just:
<a href='http://blah/download.pdf' target='_blank'>Click here to download the PDF</a>
Looking at the source for the ngSanitize module, it seems that for some reason the id attribute is not on the list of valid attributes:
https://github.com/angular/angular.js/blob/master/src/ngSanitize/sanitize.js#L206
What's the reason for not allowing the id attribute? Is it a security risk?
I'd really like to continue to use ngBindHtml if possible. Is there an API where I can add safe tags to the sanitizer's list? Or do I have to edit the source myself to add this tag?
To partially answer my own question, there doesn't seem to be an API to change the built-in whitelist, as described in this open issue:
https://github.com/angular/angular.js/issues/5900

How to select an element by classname using jqLite?

I'm trying to remove jquery from my Angular.js app in order to make it lighter, and put Angular's jqLite instead. But the app makes heavy use of find('#id') and find ('.classname'), which are not supported by jqLite, only 'tag names' (as per documentation)
wondered what do u feel would be the best approach to change it. One approach I thought about is to create custom HTML tags. for example:
change
<span class="btn btn-large" id="add-to-bag">Add to bag</span>
to
<a2b style="display:none;"><span class="btn btn-large" >Add to bag</span></a2b>
and
$element.find('#add-to-bag')
to
$element.find('a2b')
Any thoughts? other ideas?
thanks
Lior
Essentially, and as-noted by #kevin-b:
// find('#id')
angular.element(document.querySelector('#id'))
//find('.classname'), assumes you already have the starting elem to search from
angular.element(elem.querySelector('.classname'))
Note: If you're looking to do this from your controllers you may want to have a look at the "Using Controllers Correctly" section in the developers guide and refactor your presentation logic into appropriate directives (such as <a2b ...>).
angualr uses the lighter version of jquery called as jqlite which means it doesnt have all the features of jQuery. here is a reference in angularjs docs about what you can use from jquery.
Angular Element docs
In your case you need to find a div with ID or class name.
for class name you can use
var elems =$element.find('div') //returns all the div's in the $elements
angular.forEach(elems,function(v,k)){
if(angular.element(v).hasClass('class-name')){
console.log(angular.element(v));
}}
or you can use much simpler way by query selector
angular.element(document.querySelector('#id'))
angular.element(elem.querySelector('.classname'))
it is not as flexible as jQuery but what
If elem.find() is not working for you, check that you are including JQuery script before angular script....

Resources