How to specify model to a ngInclude directive in AngularJS?
NOTE: this is not my original answer but this is how I'd do this after using angular for a bit.
I would create a directive with the html template as the markup passing in the dynamic data to the directive as seen in this fiddle.
Steps/notes for this example:
- Define a directive with markup in the
templateUrl
and attribute(s) used to pass data into the directive (namedtype
in this example). - Use the directive data in the template (named
type
in this example). - When using the directive in the markup make sure you pass in the data from the controller scope to the directive (
<address-form type="billing"></address-form>
(where billing is accessing an object on the controller scope). - Note that when defining a directive the name is camel cased but when used in the markup it is lower case dash delimited (ie it's named
addressForm
in the js butaddress-form
in the html). More info on this can be found in the angular docs here.
Here is the js:
var myApp = angular.module('myApp',[]);
angular.module('myApp').directive('addressForm', function() {
return {
restrict: 'E',
templateUrl: 'partials/addressform.html', // markup for template
scope: {
type: '=' // allows data to be passed into directive from controller scope
}
};
});
angular.module('myApp').controller('MyCtrl', function($scope) {
// sample objects in the controller scope that gets passed to the directive
$scope.billing = { type: 'billing type', value: 'abc' };
$scope.delivery = { type: 'delivery type', value: 'def' };
});
With markup:
<div ng-controller="MyCtrl">
<address-form type="billing"></address-form>
<address-form type="delivery"></address-form>
</div>
ORIGINAL ANSWER (which is completely different than using a directive BTW).
Note: The fiddle from my original answer below doesn't appear to work anymore due to an error (but keeping it here in case it is still useful)
There was a discussion about this on the Google Group you can see it here.
It looks like this functionality is not supported out of the box but you can use Brice's patch as described in this post.
Here is the sample code from his jsfiddle:
<script id="partials/addressform.html" type="text/ng-template">
partial of type {{type}}<br>
</script>
<div ng-controller="MyCtrl">
<ng-include src="'partials/addressform.html'" onInclude="type='billing'"></ng-include>
<ng-include src="'partials/addressform.html'" onLoad="type='delivery'"></ng-include>
</div>
How to get different ng-model values in ng-include of the same HTML file
If you are using AngularJS v1.5+, you can use component instead of ng-include. This is an example of a component you could create
Component JS
angular
.module('app')
.component('myDetailsComponent', {
bindings: {
data: '<'
},
controller: function () {
// do whatever you need with your input here
},
templateUrl: 'my-details.component.html'
});
Component Template
<input type="text" ng-model="$ctrl.data.Name">
View
<div>
<p>Journalist's Details:</p>
<my-details-component data="companion"></my-details-component>
</div>
Edit
If you are using an older version of AngularJS, you can replicate the same functionality with a directive. For example:
Directive JS
angular
.module('myDetailsDirective')
.directive('myDetailsDirective', myDetailsDirective);
function myDetailsDirective() {
return {
restrict: 'E',
scope: {
data: '='
},
templateUrl: 'my-details.directive.html',
link: function () {
// do whatever you need with your input here
}
};
}
Directive Template
<input type="text" ng-model="data.Name">
View
The usage of the directive is exactly the same as in the case of the component:
<div>
<p>Journalist's Details:</p>
<my-details-directive data="companion"></my-details-directive>
</div>
AngularJS dynamic template with ng-include and separate template directives
What we ended up doing is this:
we have one directive:
app.directive("searchResultsContainer", function() {
restrict: "E",
templateUrl: "search-results-container.html",
controller: function($scope) {
$scope.templates = [
{ viewmode: "list", url: "search-results-list-view.html" },
{ viewmode: "grid", url: "search-results-grid-view.html" },
{ viewmode: "table", url: "search-results-table-view.html" }
]
},
link: function(scope) {
scope.toggleView = function() {
scope.templates.push(scope.templates.shift());
}
}
}
This directive is instantiated by using an ng-include directive:
<search-results-container ng-include="views/result-list.html"></search-results-container>
The used result-list.html file has this passage:
<div ng-switch on="templates[0].viewmode">
<search-results-list-view ng-switch-default></gs-search-results-list-view>
<search-results-grid-view ng-switch-when="grid"></gs-search-results-grid-view>
<search-results-table-view ng-switch-when="table"></gs-search-results-table-view>
</div>
And it has a button to toggle between views, using a simple ng-click directive:
<button ng-click="toggleViewMode()">Toggle View</button>
This button triggers the searchResultsContainer's toggleView method, described in the directive above, moving the elements of the templates array around:
scope.toggleView = function() {
scope.templates.push(scope.templates.shift());
}
The ng-switch directive listens for changes in the "viewmode" property of the first element of the templates array:
ng-switch on="templates[0].viewmode"
Such a change happens when clicking the button, thus changing the first element in the array entirely, which naturally also results in a change of the "viewmode" property, monitored by ng-switch.
The nested ng-switch-default and ng-switch-when directives react to the change and display the according element, which has the appropriate value set in "ng-switch-when".
The three children of the ng-switch each use a separate directive, here is one of them:
app.directive("searchResultsListView", function() {
return {
restrict: "E",
require: "^searchResultsContainer",
template: "<div ng-include=\"'views/list-view.html'\"></div>",
controller: function($scope) {
/* $scope stuff goes here */
},
link: function(scope, element, attrs, searchResultsCtrl) {
/* link stuff goes here */
}
}
});
Note the very important escaped quotation marks, followed by high-commas in the template's ng-include directive, as required by the ng-include directive (more info on ng-include).
Directives inside ng-include
Here is a working plunker: http://plnkr.co/edit/ilVbkHVTQWBHAs5249BT?p=preview
You got bitten by using a primitive value on the scope.
- When you put
fblogin
outside ofngInclude
it's on the same scope of the controller. ngInclude
always creates a new child scope so any directive inside it is ona child scope
.
From Understanding Scopes wiki:
Scope inheritance is normally straightforward, and you often don't even need to know it is happening... until you try 2-way data binding (i.e., form elements, ng-model) to a primitive (e.g., number, string, boolean) defined on the parent scope from inside the child scope.
It doesn't work the way most people expect it should work. What happens is that the child scope gets its own property that hides/shadows the parent property of the same name. This is not something AngularJS is doing – this is how JavaScript prototypal inheritance works.
New AngularJS developers often do not realize that ng-repeat, ng-switch, ng-view and ng-include all create new child scopes, so the problem often shows up when these directives are involved.
This issue with primitives can be easily avoided by following the "best practice" of always have a '.' in your ng-models.
What happens in your case is that scope.saveTemplate = '/set/continue';
just create a variable on the child scope which shadows scope.saveTemplate
of the parent scope (controller).
angularjs - custom directive in ng-include not working
I've changed your code a little bit so the boolean value will reside inside an object, and now you just have to watch that instead:
Controller changes:
mymodal.controller('MainCtrl', function ($scope) {
$scope.modalObj = { showModal : false };
$scope.toggleModal = function(){
$scope.modalObj.showModal = !$scope.modalObj.showModal;
};
});
Directive (main) change:
scope.$watch(function () { return scope.modalObj.showModal; }, function(value){
if(value == true)
$(element).modal('show');
else
$(element).modal('hide');
});
And also of course the lines will now refer to scope.modalObj.showModal
instead of using the parent/attr keywords, in general you should try to avoid those.
Fiddle
Different ng-include's on the same page: how to send different variables to each?
The expression passed to onload
evaluates every time a new partial is loaded. In this case you are changing the values of var
twice so by the time both partials are loaded the current value will be B
You want to pass different data to each partial/template (with the underlying html file being the same). To achieve this, as Tiago mentions, you could do it with different controllers. For example, consider the following
<body ng-controller='MainCtrl'>
<div ng-include src='"toBeIncluded.html"' ng-controller='ctrlA' onload="hi()"></div>
<div ng-include src='"toBeIncluded.html"' ng-controller='ctrlB' onload="hi()"></div>
</body>
Here, we have two partials, each with its own scope managed from their own controller (ctrlA
and ctrlB
), both children scopes of MainCtrl
. The function hi()
belongs to the scope of MainCtrl
and will be run twice.
If we have the following controllers
app.controller('MainCtrl', function($scope) {
$scope.msg = "Hello from main controller";
$scope.hi= function(){console.log('hi');};
});
app.controller('ctrlA', function($scope) {
$scope.v = "Hello from controller A";
});
app.controller('ctrlB', function($scope) {
$scope.v = "Hello from controller B";
});
And the contents of toBeIncluded.html
are
<p>value of msg = {{msg}}</p>
<p>value of v = {{v}} </p>
The resulting html would be something along the following lines
<p>value of msg = Hello from main controller</p>
<p>value of v = Hello from main controller A </p>
and
<p>value of msg = Hello from main controller</p>
<p>value of v = Hello from controller B </p>
Example here: http://plnkr.co/edit/xeloFM?p=preview
AngularJS ng-model does not work with ng-include
When you use ng-include, Angular creates a new scope, causing your variable to be overwritten to the new scope, instead of the one you wanted. As the new scope is an instance of the original scope (the one you want), you can create an object on CustomRowsCtrl; the objects are copied to the new scope as a reference, enabling you to share the same object in between child and parent scope.
Obs.: You can also use $parent, as suggested on the link below, but using pointers is a lot cleaner and if you use multiple nesting, you won't need to use $parent.$parent and so on.
Example:
On the controller:
$scope.selection = {}
On the HTML:
ng-model="selection.numLines"
More about ng-include scope:
AngularJS - losing scope when using ng-include
ng-include with ng-click raise submit - how to avoid it?
use type="submit"
with the submit button, and input
instead of button
.
Related Topics
HTML5 Canvas - Fill Circle with Image
Frozen Table Header Inside Scrollable Div
Mobile Website "Whatsapp" Button to Send Message to a Specific Number
Overlapping/Overlaying Multiple Inline Images
Should I Use <Ul>S and <Li>S Inside My <Nav>S
How to Create a Wavy Shape CSS
How to Display a Range Input Slider Vertically
Ajax HTML Vs Xml/JSON Responses - Performance or Other Reasons
How to Apply Font Anti-Alias Effects in CSS
How to Vertically Align a Table in CSS
CSS Stretch Textbox to Fill Remaining Space
CSS Styling Text Areas Like Notebook-Look
Is It Bad Design to Use Table Tags When Displaying Forms in HTML
File Opens Instead of Downloading in Internet Explorer in a Href Link