How to update variables in ng-include view - angularjs

I have a form and a view that shows data from that form. I want to separate form and view (which will be more that one).
Here is my code:
<div data-ng-controller="dataController" class="container">
<div data-ng-view></div>
<div ng-include="templates.simple" scope="data"></div>
</div>
And the included view shows initial data good, but does not react on any data change. How do I fix it?
data is and object with some fields.
templates.simple is a scope variable with template url
Code example: http://plnkr.co/edit/ibrsBaq8osYuEODGiM6O

The reason why binding is not working is you are reinitalizing an createDataController which is again creating data object for that ng-view template. This could be solve by removing createDataController controller from route.
Code
$routeProvider
.when('/', {
templateUrl: 'form.html',
//controller: 'createDataController'
})
Plunkr Here
Update
Other way would be if you want to load your controller twice still it doen't make any sense though. You could do this by writing ng-init on outside div, Instead of declaring that variable from controller.
<div data-ng-controller="createDataController" ng-init="data = {name: 'texy'}">
<div data-ng-view></div>
<div data-ng-include="'template.html'"></div>
</div>
Updated Plunkr

Related

Use ui-view as the template for state inside ui-router instead of an external template

I have an app that is currently using the angular ui-router module dependency. The only aspect of the ui-router that I'm currently employing is the ability to apply/modify $stateParams to $scope and vice versa so the URL can change the way data is displayed in the controller to a user on arrival (i.e. url?param=something will filter the data by something).
I have the following in my app.config to set the state:
$stateProvider
.state('root', {
url: '/?param',
templateUrl: 'template.html',
controller: 'listController',
params: {
param: {
value: 'something',
squash: true
}
}
});
On my homepage, template.html successfully loads when the app is instantiated as such:
<div ng-app="myApp">
<div ui-view>
</div>
</div>
However, I have reached a roadblock and realize that calling the template from within templateUrl isn't going to work, as this app is being built inside another framework and therefore needs to be called from within the homepage itself to access its full capabilities.
Being a noob at AngualrJS, I was wondering if anyone can tell me what the best way is to accomplish this while still keeping the logic of $stateParams and other ui-router capabilities intact for the future.
For instance, could I just remove the templateUrl parameter from my state and call the controller directly inside the ui-view like this:
<div ng-app="myApp">
<div ui-view>
<div ng-controller="listController">
do something
</div>
</div>
</div>
I also looked into changing the entire logic from using ui-router to simply using the $location service but I'm wondering if there is a way to accomplish this without needing to over-do everything.

ng-view for multiple form load in single page application

I am trying to load different form based on user interaction in single page application. ng-view was helpful until i had to load/hide forms in different divs of same page.
div#1: it will have catalog names populated from ng-repeat.
div#2: should populate forms ( order / schedule / list ) based on button click from top nav.
div#3: should only populate sub catalog list when user selects catalog in div#1.
index.html
<div class="left_column">
<ul>
<li ng-repeat="catalog in catalogs">{{ catalog }}</li>
</ul>
</div>
<div class="top_row">
<ng-view></ng-view>
</div>
<div class="bottom_row">
<ng-view></ng-view>
</div>
app.js
myApp.config(function($routeProvider){
$routeProvider
.when('/orderForm', {
templateUrl: '/orderForm.html',
controller: 'orderFormController'
})
.when('/scheduleForm', {
templateUrl: '/views/html/parameterForm.html',
controller: 'parameterFormController'
})
.when('/subCataloglist', {
templateUrl: '/subCataloglist.html',
controller: 'subController'
})
});
How can i load different forms at a time in single page ? is there any better example for multi view logic ?
I think that this attempt isn't correct.
I have seen only one ng-view, which could change class attached according to view url.
But here i propose much simpler architecture.
Use one view. On this view do ng-repeat in div1 as it was.
in div2 do a ng-if statement and connect it with clicking on buttons.
div three simillar - you can use ng-show or ng-if. ng-if doesn't render in dom, ng-show renders but hide.
<div class="top_row">
<form id="form1" ng-if="selval=1">
</form>
<form id="form2" ng-if="selval=2">
</form>
</div>
menu:
<ul>
<li>order</li>
<li>schedule</li>
controller attached to current html view:
$scope.sel = function(n){
$scope.selval = n;
}
As two-way binding is implemented in angular, it will work automatically.

ui-router: intermediate templates

Final Edit: working plunker with the transcluded directive.
Edit: I made a first plunker with the solution given in the first answer. It works, but it's not the desired behaviour, because the template contains all the partial.
I made a second plunker with what I hope to achieve (but it doesn't work, obviously). I think it's mostly because the template is not the parent of the partial, but it is contained in it, so ui-router doesn't understand very well what I want.
Any help with this would be greatly appreciated!
We are building a website with Angular Material and ui-router, and all our content page share the same "container", because we always want the same responsive behaviour.
The code of this generic container would be something like:
<div class="layout-content">
<div layout="column" layout-align="center">
<div layout="row" layout-align="center center">
<section class="layout-fixed-width md-whiteframe-z1" flex-sm="100" flex-gt-sm="90">
{{content placed here}}
</section>
</div>
</div>
</div>
The header can differ in all pages, so the structure we have would basically be:
The question is, how can this be achieved in ui-router? We have done some nested views, but I don't see how to do a generic template so the code could be something like:
<form>
<md-toolbar/>
<div ui-view="generic-template">
<div ui-view="my-content"></div>
</div>
</form>
Ideally we would want to define only one time the generic-template view, and use it in all our modules.
In the nested states and nested views documentation I see mostly nested state stuff, but what we want is really only a plain html template, so maybe we are over-complicating this, and an easier way is possible (I'm quite sure it's the case). I've also checked this issue, where one of the answers say that ui-router should be the solution, but not much more.
Maybe we should do a directive instead?
It can be achieved combining named views and abstract states.
The 'key' here is to define an abstract state with a view for the layout (or generic template, if we follow the nomenclature of your original post).
Abstract state:
.state('master', {
abstract: true,
views: {
generic_template: {
templateUrl: 'genericTemplate.html'
}
}
})
Then, you have to set this abstract state as parent to the child views. So, the child view will inherit the generic template view. Example:
.state('one', {
url: '/one',
templateUrl: 'one.html',
parent: 'master'
})
In your index.html, you have to use a named view for the generic template, and inside it, another unnamed view. Something like this:
<body>
<div ui-view="generic_template">
<div ui-view></div>
</div>
</body>
Here is a plunker with a complete working example.
Hope it helps.
Maybe we should do a directive instead?
A directive with a transcluded ui-view certainly seems to give you what you're looking for. This saves you from cluttering up your routing logic with something that has nothing to do with routing.
genericTemplate.html:
<div>
<p>Generic content</p>
<ng-transclude></ng-transclude>
</div>
Somewhere in your js:
angular.module('formApp')
.directive('genericTemplate', function () {
return {
replace: true,
transclude: true,
templateUrl: 'genericTemplate.html'
};
});
In your html:
<body ng-app='formApp'>
<div generic-template>
<div ui-view></div>
</div>
</body>
Edit: working plunker

Angular ui-router reloading ng-include outside ui-view

Probably it's the entire layout wrong but here is my situation, I'm using a Meanjs.org stack with Angular ui-router.
I have a layout like this:
<div data-ng-include="'/modules/core/views/header.client.view.html'"></div>
<div id="page-content" class="clearfix" fit-height>
<div id="wrap" data-ui-view="" class="mainview-animation"></div>
</div>
Now I need to reload the controller inside the header.client.view.html when I change the $state.
For example when I'm in the sign-in page and I login I need to reload the header controller, but having this it's not possible because the ui-router change only the ui-view part with the relative template:
// this change only ui-view, doesn't care about the ng-include before
state('home', {
url: '/',
templateUrl: 'modules/core/views/home.client.view.html',
});
I found the possibility to add more ui-view to the state so I could add a ui-view2 for the header instead using the ng-include but this means having the ui-view2 on each state.
Any suggest?
You might not need to "reload the controller" every time the state changes, instead make your controller react to the state change on the fly and update its properties.
Check out the ui-router $stateChangeSuccess event.
First at all you need to listen #Matti Virkkunen
It's better to listen the state in your header's controller with "$stateChangeSuccess"
So you just have to declare a controller for your header. And inside your header controller add something like this.
$scope.$on('$stateChangeSuccess', function () {
// Do what you want for example check if the current state is home with $state.is('home');
});
Do not forget to declare your controller in your template
<div data-ng-controller="HeaderController" data-ng-include="'/modules/core/views/header.client.view.html'"></div>
<div id="page-content" class="clearfix" fit-height>
<div id="wrap" data-ui-view="" class="mainview-animation"></div>
</div>

ng-repeat with ng-include not working

I am trying to use an ng-repeat that includes an ng-include. The problem is that the first element in the ng-repeat is just the ng-include template with none of the data from the ng-repeat filled in. Is there a way I can somehow bind the template from the ng-include so it works on the first ng-repeat?
<div ng-repeat="item in items">
<div ng-include src="'views/template.html'"></div>
</div>
For example, if my ng-repeat contains 10 items, then the first item that is rendered will just be the empty template. Items 2-10 WILL be rendered as they should be. What am I doing wrong?
First make sure that the data that is contained in the first index of items actually has the data that you want.
One possible solution to your problem would be to simply not show the first index of the ng-repeat:
<div ng-repeat="item in items" ng-show="!$first">
<div ng-include src="'views/template.html'"></div>
</div>
This may not actually tackle the root of your problem, but it may still get your application working a bit more like what you expect.
Another possible solution:
<div ng-repeat="item in items" ng-include="'views/template.html'"></div>
see example here:
http://plnkr.co/edit/Yvd73HiFS8dXvpvpEeFu?p=preview
One more possible fix just for good measure:
Use a component:
html:
<div ng-repeat="item in items">
<my-include></my-include>
</div>
js:
angular.module("app").directive("myInclude", function() {
return {
restrict: "E",
templateUrl: "/views/template.html"
}
})
I ran into the same problem, and finally figured out that the first element has not been fetched and compiled in time for the first ng-repeat iteration. Using $templateCache will fix the problem.
You can cache your template in a script tag:
<script type="text/ng-template" id="templateId.html">
<p>This is the content of the template</p>
</script>
Or in your app's run function:
angular.module("app").run(function($http, $templateCache) {
$http.get("/views/template.html", { cache: $templateCache });
});
You can also use $templateCache inside your directive, although it's a bit harder to setup. If your templates are dynamic, I would recommend creating a template cache service. This SO question has some good examples of template caching inside a directive and a service:
Using $http and $templateCache from within a directive doesn't return results
Using a directive worked for me: https://stackoverflow.com/a/24673257/188926
In your case:
1) define a directive:
angular.module('myApp')
.directive('mytemplate', function() {
return {
templateUrl: 'views/template.html'
};
});
2) use your new directive:
<mytemplate />
... or if you're concerned about HTML validation:
<div mytemplate></div>

Resources