I am confused by the Marionette (2.3.0) documentation from the link below that says the Application Regions feature is deprecated. A Layout View should be used instead. Does that mean I should not use MyApp.addRegions() any more? Then how should I add my Layout View to my application?
http://marionettejs.com/docs/marionette.application.html#application-regions
Application Regions
Warning: deprecated This feature is deprecated. Instead of using the
Application as the root of your view tree, you should use a Layout
View. To scope your Layout View to the entire document, you could set
its el to 'body'. This might look something like the following:
var RootView = Marionette.LayoutView.extend({ el: 'body' });
I will like to explain with a very simple example the usage of layout view in marionette.
html
<div id="appDiv"></div>
<script type="text/template" id="mainTemplate">
<div id="div1"></div>
<div id="div2"></div>
</script>
<script type="text/template" id="itemTempFirst">
<p>some text item 1 view</p>
<p>some text item view 1</p>
</script>
<script type="text/template" id="itemTempSecond">
<p>some text item 2 view</p>
<p>some text item view 2</p>
</script>
JS Code:--
var app = new Marionette.Application();
var LayoutViewObj = Marionette.LayoutView.extend({
template:"#mainTemplate",
el:"#appDiv",
regions:{
reg1:"#div1",
reg2:"#div2"
}
});
var layoutViewInstance = new LayoutViewObj();
layoutViewInstance.render();
var ItemView1Obj = Marionette.ItemView.extend({
template:"#itemTempFirst"
});
var ItemView2Obj = Marionette.ItemView.extend({
template:"#itemTempSecond"
});
var item1 = new ItemView1Obj();
var item2 = new ItemView2Obj();
layoutViewInstance.getRegion("reg1").show(item1);
layoutViewInstance.getRegion("reg2").show(item2);
Please note I was trying without el element earlier , but i got no luck and as I used el:"#someElem" life got easier
Related
I'am using fullcalender and need to change some navigation buttons with AngularJS. I do not have much experience with AngularJS so the JS Code would be somthing like this:
var filter = $(".fc-filter-button");
filter.html("<i class='fas fa-filter'></i>");
filter.attr("id", "dropdownFilterButton");
But how can i archive this and some other usual JS/JQuery Tasks with AngularJS. I know i can use JQuery too but want to do it in the right Angular way.
I tried something like this:
element[0].getElementsByClassName('fc-filter-button').html("<i class='fas fa-filter'></i>")
or
var queryResult = element[0].querySelector('.fc-filter-button');
angular.element(queryResult).html("<i class='fas fa-filter'></i>")
How can i make these changes without touching the fullcalender code itself.
Take a look at the NgSanitize module "The ngSanitize module provides functionality to sanitize HTML".
Here's an basic example which should get you going in the right direction
angular.module('app', ["ngSanitize"])
.controller('myCtrl',function($scope){
$scope.content = "<p>The initial html</p>";
$scope.changeHtml = function(){
$scope.content = "<h3>The changed html</h3>";
};
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.2/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.2/angular-sanitize.min.js"></script>
<div ng-app="app" ng-controller="myCtrl">
<button ng-click="changeHtml()">Change html</button>
<div ng-bind-html="content">
</div>
</div>
I am trying to create a tooltip based from from this post
Angular-UI-Bootstrap custom tooltip/popover with 2-way data-binding
I successfully created the popup but I have trouble delivering the content to my popover.html
I added this to my script.js
var app = angular.module('myApp', ['ui.bootstrap', 'ian.bootstrap']);
app.controller('myCtrl', function ($scope) {
$scope.item = {
title: 'Original Title',
content:'content 1' //newly added item
};
$scope.text = 'Click me';
});
and I want to display it in my popover.html
<div class="popover-content">
{{item.content}}
</div>
It doesn't show anything. Can someone help me about it? thanks a lot!
my plunker
http://plnkr.co/edit/5pBZ9qq79OPl2tGEeYYV?p=preview
Here is your updated working Plunkr
Basically you have to pass the attr iantooltip-content with the binding of the content item, not the raw text, and after in the directive pass in the directive isolate scope options the binding of the content like :
iantooltipContent: '='
Just change the appenToBody variable and you're done.
You should read the docs for more infos about Angular directive :)
You can add the ng-controller in your div and then specify the controller name like so :
<div class="popover-content" ng-controller='myCtrl'>
{{item.content}}
</div>
Before the use cases, the basic syntax to create a custom directive.
For all the code samples in this page I started from the angular-seed template.
Starting from the angular-seed skeleton is quite easy to extract a model to begin to implement custom directives.
<html ngApp="myApp">
...
<div my-first-directive></div>
<script src="lib/angular/angular.js"></script>
<script src="js/app.js"></script>
<script src="js/directives.js"></script>
...
</html>
I'm running into a problem getting Backbone.Marionette to cooperate with Twitter Bootstrap. Bootstrap expects markup to conform to predefined patterns in order to work, but the way that Backbone and Marionette handle things, it seems to be impossible to use a Marionette.Layout to generate Bootstrap-compliant markup for a navbar with an embedded dropdown.
Here's the problem:
Let's say I have a Marionette.Layout representing the navbar, and I want to have a region, where I will put the CollectionView or CompositeView that manages the items in the dropdown. The region is a selector, so in this case if we have:
<div class="navbar">
<ul class="nav">
<li>Static item</li>
<li id="dynamic-dropdown"></li>
</ul>
</div>
Then the Layout would specify the region for the dynamic dropdown as follows:
Marionette.Layout.extend({
regions: {
dropdown: '#dynamic-dropdown'
}
...
});
I would then have a CompositeView that takes care of rendering the dropdown item models, specifies the extra markup for the Bootstrap dropdown, and so forth. The problem is that it appears to be impossible to make #dynamic-dropdown be the $el for the CompositeView, as Backbone always inserts an extra div (or whatever you specify in tagName). In order for the dropdown to appear as expected, I need to get rid of that extra element and have the view's root be #dynamic-dropdown.
I've put together a jsfiddle illustrating what I mean.
tl;dr How do I make a View's root element be the region specified in a Marionette.Layout?
You just need to make sure that the markup that is generated in the end follows the same as required by Bootstrap (use the console to debug).
The required markup is as follows:
The markup generated by your code has the following problems:
So, to fix it you have to change your nav template to:
<script type="text/html" id="nav">
<div class="navbar">
<ul class="nav" id="dropdown">
</ul>
</div>
</script>
And your views to render <li> instead of <div>
var DropdownItem = Marionette.ItemView.extend({
tagName: 'li',
template: "#dropdown-item"
});
var DropdownView = Marionette.CompositeView.extend({
template: "#dropdown-collection",
className: 'dropdown',
tagName: 'li',
itemView: DropdownItem,
itemViewContainer: '#dropdown-items'
});
Here is the working version: http://jsfiddle.net/7auhR/6/
I have been trying to learn backbone.js, but I can't figure out why my click event isn't firing when I click the home link. I'm fairly new to backbone and I'm just not sure what am I missing? I've looked up a bunch of different tutorials on the net, but can't seem to find the lose hole. Please help!
Backbone.js
var HomeView = Backbone.View.extend({
el: $('.content'),
events:{
"click #home": "animateNavigation"
},
initialize: function(){
_.bindAll(this, 'displayTrips');
// Add the model collections
this.collection = new ModelList();
this.collection.bind('add', this.displayTrips); // Collection event binder
},
animateNavigation: function(){
alert('test');
return false;
},
displayTrips: function(params){
var items = params.get('data');
}
});
var home_view = new HomeView();
HTML
<div class="content">
<div class="left">
<ul>
<li>
<div class="nav_arrow"></div>
<a href="home" class="active" id="home">
<img alt="Home" src="/assets/img/nav/left/star.png">
<span>Home</span>
</a>
</li>
<li>
<a href="tropical" id="tropical">
<img alt="Tropical" src="/assets/img/nav/left/fins_grey.png">
<span>Tropical</span>
</a>
</li>
</ul>
</div>
</div>
You're finding the element at the time the model is declared. If you have your script in the header or anywhere before this content, that element doesn't exist yet. I don't know that there should be any good reason to use $('.content') here anyway, just use '.content'
Edit: Well, I see you are also declaring a new instance of your view as well. I don't know if that line represents literally what you have in your script, or you just put it there for the purpose of demonstrating your basic use. I generally define the views and models elsewhere from the page logic (which would have the instances of those things), primarily so that I can reuse them.
Could you add
console.log(home_view.$el.html());
at the end, to check the Dom Element of home_view please. I assume that something goes wrong when binding the view to the Dom element.
I found this solved it for me:
var home_view = new HomeView({el:$('.content')});
UPDATE - better than that, do this:
var home_view = new HomeView({el:'.content'});
then this.$el will work as the above post says
I am trying out Backbone.Marionette and I am confused as to why my Layouts and ItemViews keep generating extra divs.
example is in Coffee btw.
AppLayout = Backbone.Marionette.Layout.extend
template: "#my-layout",
regions:
menu: "#menu",
content: "#content"
MyMenuView = Backbone.Marionette.ItemView.extend
template: '#project_wiz_nav_template'
MyContentView = Backbone.Marionette.ItemView.extend
template: '#project_setup_template'
MyApp = new Backbone.Marionette.Application()
MyApp.addRegions
mainRegion: '#project'
MyApp.addInitializer ->
layout = new AppLayout()
MyApp.mainRegion.show(layout)
layout.menu.show(new MyMenuView())
layout.content.show(new MyContentView())
MyApp.start()
This is what index.html contains:
<div id='project'></div>
<script type='text/template' id='project_wiz_nav_template'> <h2>HI</h2> </script>
<script type='text/template' id='project_setup_template'> <h2>WORLD</h2> </script>
<script id="my-layout" type="text/template">
<h2>Hello!</h2>
<div id="menu"></div>
<div id="content"></div>
</script>
This is what it produces:
<div id="project">
<div>
<h2>Hello!</h2>
<div id="menu">
<div>
<h2>HI</h2>
</div>
</div>
<div id="content">
<div>
<h2>WORLD</h2>
</div>
</div>
</div>
</div>
As you can see, it keeps generating extra divs for the views and the layouts. I've tried adding el: '#menu' and el: '#content' to no avail.
This is not because of Marionette. Backbone generates a <div> class for you by default. You can set the tag via the tagName attribute. See comments on the question for duplicates of this.
A hacky workaround, but jQuery's closest() actually did the job for me. Rather than using the returned myView.el directly, I'm using $(myView.el).closest("div").html() -- as I said, hacky, but as a short-term fix it's working.
I was tinkering with this tutorial: http://davidsulc.com/blog/2013/02/03/tutorial-nested-views-using-backbone-marionettes-compositeview/comment-page-1/#comment-3801, which takes a nested model and creates an accordion view using Bootstrap. I wanted to do the same with his starting point, only using the jQueryUI accordion widget, which is the reason I needed an unwrapped view coming back -- hence the filtering with closest().
Other than adding the jqueryUI links and changing the returned HTML as delineated above, it's working pretty well: http://dartsleague.parentleafarm.com/superheroes/
Specify your el property. I think that will fix it:
http://documentcloud.github.com/backbone/#View-el