BackboneJS Display multiple collections in one <ul>-Element - backbone.js

I would like to know if it's possible to diplay multiple collections inside one <ul>-element?
for example when I have multiple views, in each view I have a collection like this:
Collection = Backbone.Collection.extend({
url: function() {
return '/path/to/JSON/file';
}
});
Now I want to display all Collections inside the same <ul>-element so that in my frontend it would give me the output
<ul>
<li>Data from Collection 1</li>
<li>Data from Collection 1</li>
<li>Data from Collection 2</li>
<li>Data from Collection 2</li>
<li>Data from Collection 3</li>
<li>Data from Collection 3</li>
</ul>
Is that possible? If yes then how?
Thanks in advance...
[EDIT]
Ok, so in my mainView I have:
Artist.View = Backbone.View.extend({
template: 'artistchannel',
beforeRender: function() {
var artistinstagramCollection = new ArtistInstagram.ArtistInstagramCollection();
artistinstagramCollection.artist_id = this.artist_id;
this.insertView('.socialMedia', new ArtistInstagram.View({collection:artistinstagramCollection}));
artistinstagramCollection.fetch();
var artisttwitterCollection = new ArtistTwitter.ArtistTwitterCollection();
artisttwitterCollection.artist_id = this.artist_id;
this.insertView('.socialMedia', new ArtistTwitter.View({collection: artisttwitterCollection}));
artisttwitterCollection.fetch();
var artistfacebookCollection = new ArtistFacebook.ArtistFacebookCollection();
artistfacebookCollection.artist_id = this.artist_id;
this.insertView('.socialMedia', new ArtistFacebook.View({collection: artistfacebookCollection}));
artistfacebookCollection.fetch();
Like mentioned before, each Collection is bound to its own view:
function (App, Backbone) {
var ArtistInstagram = App.module();
ArtistInstagram.View = Backbone.View.extend({
tagName: 'li',
template: 'instagram',
initialize: function() {
this.listenTo(this.collection, 'all', this.render)
},
serialize: function() {
return this.collection ? this.collection.toJSON() : [];
}
});
ArtistInstagram.ArtistInstagramCollection = Backbone.Collection.extend({
url: function() {
return '/myproject/index.php/api/social_feeds/instagram/' + this.artist_id;
}
});
return ArtistInstagram;
}
The same above goes for Twitter and Facebook. So I have 3 modules.
Then in the template artistchannel there is a section where I have:
<div class="socialMediaDiv">
<ul class="socialMedia"></ul>
</div>
And my HandlebarsJS-HTML template looks like:
{{#each this}}
<li>
<img src="{{title}}" />
<section class="ip">
<p>{{description}}</p>
<h3>
<time class="timeago" datetime="{{pubDate}}"></time>
{{type}}
</h3>
</section>
</li>
{{/each}}
When I do it like this it generates 3 <li>-elements, so the structure is like:
<ul>
<li>
<li>some results from collection 1</li>
<li>...</li>
<li>...</li>
<li>...</li>
</li>
<li>
<li>some results from collection 2</li>
<li>...</li>
<li>...</li>
<li>...</li>
</li>
<li>
<li>some results from collection 3</li>
<li>...</li>
<li>...</li>
<li>...</li>
</li>
</ul>
What am I doing wrong??
By the way, I'm using backbone's layoutmanager

It's certainly possible. When you render the collection view, just append to the container element (el or $el) instead of replacing its html.

Related

Angular.js - ng-repeat not working

Angular.js is pretty new to me. I have learned before the $scope method for the controller and now trying the "this" method. For some reason I can not get my ng-repeat to work. here's my code:
HTML:
<ul class="nav nav-pills">
<li><a ng-click="myCtrl.tab=1" href>one</a></li>
<li><a ng-click="myCtrl.tab=2" href>two</a></li>
<li><a ng-click="myCtrl.tab=3" href>three</a></li>
</ul>
<div ng-controller="imageContr as imageCtrl">
<div ng-show="myCtrl.tab === 1" class="tab">
<h3>ONE title</h3>
<p>hello</p>
<li ng-repeat="item in gallery">
<img alt="imagealt" ng-src="{{item.photo}}">
</li>
</div>
<div ng-show="myCtrl.tab === 2" class="tab">
<h3>TWO title</h3>
<p>how are</p>
</div>
<div ng-show="myCtrl.tab === 3" class="tab">
<h3>THREE title</h3>
<p>you?</p>
</div>
</div>
</section>
</body>
</html>
APP.JS:
(function() {
var app = angular.module('myApp', []);
app.controller('myController', function() {
this.tab = 1;
});
app.controller('imageContr', function() {
this.gallery = images;
var images = {
photo: 'image1.jpg'
};
});
})();
Declare images before you assign it, and make it an array
var images = [{ photo: 'image1.jpg' }];
this.gallery = images;
Then in your view:
<li ng-repeat="item in imageCtrl.gallery">
<img alt="imagealt" ng-src="{{item.photo}}">
</li>
You are storing the gallery on this of the controller (which is basically the $scope), hence you need to access it in the template via imageContr as well:
<li ng-repeat="item in imageCtrl.gallery">
<img alt="imagealt" ng-src="{{item.photo}}">
</li>
You could also consider making gallery an array, so can easily iterate over it. Or you need to use the "iterate over object properties"-syntax:
<div ng-repeat="(key, value) in myObj"> ... </div>

Get Title of clicked menu-li

how can I get the title of the clicked list element? Unfortunately, the following snippet returns an 'undefined'
HTML
<ul class="nav nav-second-level collapse">
<li>
<span>Echocardiogram</span>
</li>
<li>
<span>Echocardiogram</span>
</li>
JS
$scope.menuClick = function(linkTitle) {
var linkText = angular.element(linkTitle).data('title');
console.log(linkText);
};
Here is a simple solution. First you should angularise your code by storing your menu items in a scope variable. You can then use ng-repeat to iterate through your items. You can store the corresponding title as well and then reference that title through your ng-click.
<div ng-controller="MyCtrl">
<ul class="nav nav-second-level collapse">
<li ng-repeat="item in listItems">
<a href="#" ng-attr-title="item.title" ng-click="getTitle(item.title)">
<span>{{ item.name }}</span>
</a>
</li>
</ul>
function MyCtrl($scope) {
$scope.listItems = [{
"name": "Echocardiogram",
"title": "Cardiology: Test 1"
}, {
"name": "Echocardiogram",
"title": "Cardiology: Test 2"
}];
$scope.getTitle = function (title) {
alert(title);
}
}
JSFiddle
You could use the click event. And reference the target element (<a>) and read it's title propery.
Html:
<a href="#" class="menuLink" ng-click="menuClick($event)" title="Cardiology: Test 1">
Controller :
$scope.menuLink =function (event){
var title = angular.element (event.target).attr ('title');
}

How close all other menu when click specific menu in angular js?

I have use toggle menu from simple toggle .but my problem that when we click on specific menu then all other menu should be close like as accordion menu.
Directive :
element.bind('click', function() {
var content = target.querySelector('.slideable_content');
if(!attrs.expanded) {
content.style.border = '1px solid rgba(0,0,0,0)';
var y = content.clientHeight;
content.style.border = 0;
target.style.height = y + 'px';
} else {
target.style.height = '0px';
}
attrs.expanded = !attrs.expanded;
});
when click on slide above code will execute.i need some logic like close all toggle which class name slidable_content
My Code is here : Plunker
#Michael is right, you can use the two way data binding to do that easily
<section>
<ul>
<li>
<span ng-click="isExpanded = ! isExpanded">Show 1</span>
</li>
<li ng-show="isExpanded" slider id="test2">
<p>Are to hide and show adf</p>
</li>
</ul>
</section>
So, you can control the state of the other menus if you want
UPDATE:
Try this:
<section>
<ul>
<li slider-toggle ng-click="expandItem = 1">Slider 1</li>
<li ng-if="expandItem == 1" slider id="test1">
<p>Are to hide and show</p>
</li>
<li slider-toggle ng-click="expandItem = 2">Slider 2</li>
<li ng-if="expandItem == 2" slider id="test2">
<p>Are to hide and show</p>
</li>
<li slider-toggle ng-click="expandItem = 3">Slider 3</li>
<li ng-if="expandItem == 3" slider id="test3">
<p>Are to hide and show</p>
</li>
<li slider-toggle ng-click="expandItem = 4">Slider 4</li>
<li ng-if="expandItem == 4" slider id="test4">
<p>Are to hide and show</p>
</li>
</ul>
</section>
In this way you can create an accordion menu, just getting the value of the element that you want to show and validating it with the ng-if directive (you can use ng-show if you want, you can find the difference here: docs.angularjs.org/api/ng/directive)
Note:
You shouldn't get elements of the DOM with jquery or javascript selectors, if you want to control an element of the DOM you can use a directive, as an example:
script.js:
.directive('someDirective',function(){
return{
restrict:'A',
scope:true,
templateUrl:'someTemplate.html',
link: function(scope, element, attrs){
console.log(element) //This will be your element
}
}
})
main.html:
<li some-directive ng-click="expandItem = 4">Slider 4</li>
UPDATE
If you want to close the current open item, you can control the open/close state with a function.
Try this:
main.html
<body ng-app="myApp">
<section ng-controller="myCtrl">
<ul>
<li slider-toggle ng-click="setCurrentItem(1)">Slider 1</li>
<li ng-show="currentItem == 1" slider id="test1">
<p>Are to hide and show</p>
</li>
<li slider-toggle ng-click="setCurrentItem(2)">Slider 2</li>
<li ng-show="currentItem == 2" slider id="test2">
<p>Are to hide and show</p>
</li>
<li slider-toggle ng-click="setCurrentItem(3)">Slider 3</li>
<li ng-show="currentItem == 3" slider id="test3">
<p>Are to hide and show</p>
</li>
<li slider-toggle ng-click="setCurrentItem(4)">Slider 4</li>
<li ng-show="currentItem == 4" slider id="test4">
<p>Are to hide and show</p>
</li>
</ul>
</section>
</body>
app.js
var myApp = angular.module('myApp', []);
myApp.controller("myCtrl", ["$scope", function ($scope) {
$scope.currentItem = null;
$scope.setCurrentItem = function (itemId) {
if(itemId == $scope.currentItem){
$scope.currentItem = null;
}else{
$scope.currentItem = itemId;
}
}
}])

Detect user selection for li

I have a list of items ("locals" array) which I show in a list
<ul class="list-group">
<li ng-repeat="loc in locals" class="list-group-item"><a href="" data-id={{loc.ID}}>{{loc.location}}</a>
</li>
</ul>
I want the user to be able to select an item, and then to use this item in code.
What is the preferred way to do it.
Also I am creating the application for mobile, so I should be able to know that the user chose this item in mobile( and not just use mouseclick for example).
You can make use of angular js ng-click event (on the li item where ng-repeat is and do something like this: fiddle
code snippet of controller:
function MyCtrl($scope) {
$scope.templateList = [{id:1, name: 'Template1'}, {id:2, name: 'Another Template'}]
$scope.template = {};
$scope.setValue = function(list) {
$scope.template.template_id = list.id;
$scope.template.template_name = list.name;
}
}
Of HTML:
<div ng-app>
<form ng-controller="MyCtrl">
<input type="hidden" name="template_id" ng-model="template.template_id" />
<input type="text" name="template_name" ng-model="template.template_name" />
<ul>
<li ng-repeat="list in templateList" ng-click="setValue(list)">{{list.name}}</li>
</ul>
</form>
</div>
Try this:
In html,
<ul class="list-group">
<li ng-repeat="loc in locals" class="list-group-item">
<a href="" data-id={{loc.ID}} ng-click="selectLoc(loc.location)">
{{loc.location}}
</a>
</li>
</ul>
In JS,
$scope.selectLoc = function(location){
console.log(location);
//Here you will get the selected location.
var SomeVar = location;
}
Hope this helps....

How can create a dynamic menu depending on the user's rights, in angularjs?

There is two similar questions:
dynamic menu items using AngularJS
How can I show or hide some buttons depend on the user's rights, in angularjs?
I need to create a dynamic menu exactly like in the first similar question exept I cannot hardcode the rights in my page. An adminitrator can create custom roles and chose wich menu item this role can see.
<li class="dropdown"><img role="button" class="dropdown-toggle" data-toggle="dropdown" ng-src="{{avatarUrl}}" />
<ul class="dropdown-menu pull-right" role="menu">
<li ng-show="???"><a ng-click="action01()">Action one</a></li>
<li ng-show="???"><a ng-click="action02()">Action two</a></li>
<li ng-show="???"><a ng-click="action03()">Action tree</a></li>
<li ng-show="???"><a ng-click="action04()">Action four</a></li>
</ul>
</li>
How should I imagine my strategy?
I would create something like a HeaderController an attach to it a function that tells if a given role can do the given action. Presumably you have the ACL stored somewhere so perhaps you can create a service for it. Something like this:
controller('HeaderController', ['$scope', 'Acl', function($scope, Acl) {
$scope.roleCanDo = function(role, action) {
return Acl.roleCanDo(role, action);
}
}])
and your view would be like this:
<li class="dropdown"><img role="button" class="dropdown-toggle" data-toggle="dropdown" ng-src="{{avatarUrl}}" />
<ul class="dropdown-menu pull-right" role="menu">
<li ng-show="roleCanDo(currentUser.role, 'action01')"><a ng-click="action01()">Action one</a></li>
<li ng-show="roleCanDo(currentUser.role, 'action02')"><a ng-click="action02()">Action two</a></li>
<li ng-show="roleCanDo(currentUser.role, 'action03')"><a ng-click="action03()">Action tree</a></li>
<li ng-show="roleCanDo(currentUser.role, 'action04')"><a ng-click="action04()">Action four</a></li>
</ul>
</li>
Obviously the actual code will depend on your current system but you get the idea.
It's very simple to implement Creating dynamic menu from database data using AngularJS
Suppose we have a table in our database for navigation menus like,
Table structure for dynamic menu
Write below code for fetch menus from database
public JsonResult GetSiteMenu()
{
using (MyDatabaseEntities dc = new MyDatabaseEntities())
{
var menu = dc.SiteMenus.ToList();
return new JsonResult { Data = menu, JsonRequestBehavior = JsonRequestBehavior.AllowGet };
}
}
and here is the angularjs controller
var app = angular.module('MyApp', []);
app.controller('menuController', ['$scope', '$http', function ($scope, $http) {
$scope.SiteMenu = [];
$http.get('/home/GetSiteMenu').then(function (data) {
$scope.SiteMenu = data.data;
}, function (error) {
alert('Error');
})
}])
HTML Code
<div ng-app="MyApp">
<div ng-controller="menuController">
#* Here first of all we will create a ng-template *#
<script type="text/ng-template" id="treeMenu">
{{menu.Name}}
#* We will create submenu only when available *#
<ul ng-if="(SiteMenu | filter:{ParentID : menu.ID}).length > 0">
<li ng-repeat="menu in SiteMenu | filter:{ParentID : menu.ID}" ng-include="'treeMenu'"></li>
</ul>
</script>
<ul class="main-navigation">
#* Here we will load only top level menu *#
<li ng-repeat="menu in SiteMenu | filter:{ParentID : 0}" ng-include="'treeMenu'"></li>
</ul>
</div>
</div>

Resources