I have a controller I am calling an API on MVC.
This API returns me back a partial view, This partial view is associated with my controller from which I am calling the API .
Now as soon as I getting the partial view back, I am vanishing the html of the view and then re-rendering the view.
but my controller method never get initated, I guess because the controller is already initiated.
Question is can I call method of controller when it loads back.
html :
<div id="pageholder">
<-- here is my view , which I am changing thru API , and I want to re render it, and also want to perform certain controller methods -->
</div>
ANGULAR :
$http({
method: 'POST',
url: url,
data: {
config: item,
parameter: itemParametrs
}
}).success(function(data, status) {
$('#pageholder').empty();
$scope.username="username";
$('#pageholder').html(data);
});
PLEASE HELP!
You need to compile that new HTML you get. No directive or controller will be watched by Angular if you dynamically write HTML:
.success(function(data, status) {
$scope.username="username";
var $pholder = $('#pageholder');
$pholder.empty();
$pholder.html(data);
// Recompile the HTML so angular can process it
$compile($pholder)($scope);
});
PS: you will need to get the $compile service in your directive/controller (the same way you get $http)
Related
I am having on angular page.
Page1 :
In which configuration is
.when('/Test/:empId', {
templateUrl:'/Templates/test.html',
controller: 'TestController'
})
.when('/Test/:depId', {
templateUrl:'/Templates/test1.html',
controller: 'Test1Controller'
})
Then i have another page
Page 2:
This page is normal mvc razor page having button
Button1
On click of that button i want to show modal which contain
Page1
So i wrote
$.ajax({
url: '/Templates/test.html',
type: 'GET',
success: function (responce) {
var elem = angular.element(responce);
$('#testModalBody').html(elem);
$('#testModal').modal('show');
//console.log('test responce');
}
});
I am just getting html response, it does not execute 'TestController'
So the scope variables are not getting values declared in TestController, and not able to see data html pages. Just see static html template.
Instead of using $.ajax, you should use $http service of Angular JS.
Instead of doing like this $('#testModalBody'), you can use ng-bind-html.
To bind HTML please read below link.
https://www.w3schools.com/angular/ng_ng-bind-html.asp
Does anyone know why my $scope.userData isn't rendering in my View when using angular-route and Angular's $location service together?
My Situation:
In the code example below, I have an index page which iterates through users, allUsers, using angular's ng-repeat, as follows: ng-repeat="user in allUsers [note, for simplicity, I have left out the function in my controller snippet below that delivers allUsers, but is working correctly].
For each user, there is an edit button, which should run the $scope.findOne function, passing in the user itself as a parameter.
In my $scope.findOne function, a new partial is loaded using the $location service, and $scope.userData is updated to reflect this user. I want to access $scope.userData now on the new partial (my problem).
Problem:
The new partial loads, the user object seems to pass along fine, however $scope.userData becomes inaccessible on the front-end.
PseudoCode (What I'd Like):
// Iterate through allUsers (`user in allUsers`)
// When Edit button is clicked for `user`:
// Fire off `findOne` function passing in `user`
// Set `$scope.userData` to `user`
// Load `html/edit.html` partial
// Show `$scope.userData` on the page (should be `user` info):
PseudoCode (What's Happening Instead):
// Iterates through allUsers (`user in allUsers`)
// When Edit button is clicked:
// Fires off `findOne` function and passes `user`
// Sets $scope.userData` (console logging it after shows changes)
// Loads `html/edit.html`
// **DOES NOT show `$scope.userData` and appears empty.**
Angular Module Setup:
Both the /index.html page and the /edit.html page appear to be setup correctly with the appropriate controller assignments:
// Define Module:
var app = angular.module('app', ['ngRoute']);
// Define Routes:
app.config(function($routeProvider) {
$routeProvider
.when('/', {
templateUrl: 'html/index.html', // root route partial
controller: 'userController',
})
.when('/edit/:id', {
templateUrl: 'html/edit.html', // edit page partial
controller: 'userController',
})
.otherwise({
redirectTo: '/',
})
});
Angular Controller:
My angular controller (allUsers function now shown) shows the findOne function I'm trying to access, along with the use of the $location service:
app.controller('userController', ['$scope', 'userFactory', '$location', function($scope, userFactory, $location) {
$scope.findOne = function(myUser) {
$scope.userData = myUser;
console.log($scope.userData); // shows changes...(?)
$location.url('/edit/' + myUser._id); // redirects and partial loads OK...
};
}]);
In the following Index HTML example, clicking the Edit button triggers the $scope.findOne function fine, redirects the page and updates $scope.userData (console logs OK), but on the partial itself, $scope.userData does not seem to reflect the changes (what gives?):
Index Page HTML:
<div ng-repeat="user in allUsers">
<h1>{{user.username}}</h1>
<button ng-click="findOne(user)">Edit</button> <!-- runs findOne -->
</div>
Edit Partial HTML:
<h2>Edit:</h2>
{{userData}} <!-- $scope.userData displays nothing? -->
Summary:
Why does {{userData}} in my Edit Partial HTML not show anything?
I found a solution to my needs by creating a new controller, and having this other controller take over when the /edit.html page is loaded. The controller queries the DB on page load for the user based on req.params.id. This worked and I was able to carry on, but I have two separate controllers, when instead, I'd like to manage all CRUD operations from a single controller for my Users...(is this bad practice?)
I had initially tried the solution above, but got stuck with the $scope issue as outlined here in this write up. Any ideas what I'm doing wrong in getting my above data to render in my View? Your time and patience reading is genuinely valued! Thank you Stack Community!
My guess (mostly b/c I use angular-ui-router) is that when you navigate to the edit partial, a new controller is being instantiated, so the data on the $scope is lost.
Here are two common approaches I've seen:
Do what you described above to query the server for the user data using route params. Consider enabling the caching option for $http so it doesn't have to hit the server each time... but then you need to invalidate the cache when the data changes
Create a service that queries the server for the list of users. This service makes the user list available to the controller, and returns an individual user for editing.
I'm building a rest api with fosrestbundle and I manage the frontend with angular and Twig template. One on my url address looks like this :
http://mywebsite/myroute/idContain
When I load the url in my browser, in a twig template (kind of html), I retrieve the parameter "idContain" (comming from a fosrestbundle controller) with ng-init of angularjs like this :
<div class="container-fluid" ng-init="getContainByID({{ idContain }})">
//...lot html div with angularjs directives
</div>
And immediately, ng-init will go to my angularJS app finds getContainByID(idContain) to run it.
This one looks like this :
angular.module("myApp", ["ngSanitize", 'angular.filter', 'ui.tinymce', ...])
.config(function($interpolateProvider, ...) {
$interpolateProvider.startSymbol('{[{').endSymbol('}]}');
})
.controller("myCtrl",function ($filter,..., myService)
{
// lot of code...
$scope.getContainByID = function(idContain)
{
$scope.currentContain = myService.getContains(idContain);
$scope.containRoot = $scope.currentContain.contain.containRoot;
...
}
// lot of code...
}
The fact is that, myService.getContains(idContain) come from my rest service looking like this :
angular.module("MyServiceRest", ['ngResource'])
.factory("myService", function ($rootScope, $resource) {
var apiData = $resource(
"/api", {},
{
...
"getContains": {method: 'GET', isArray: false, url: "mywebsite/api/myroute/:containid"}
...
});
return {
getContains: function (idContain) {
return apiData.getContains({containid: idContain});
}
}
});
Now the problem is, when I run my angularjs App, $scope.containRoot doesn't wait until myService.getContains(idContain) (coming from my asynchroeous $resource service) finished to load, and caused errors making my webapp crash.
How can I do, to force $scope.containRoot and the rest of my angular code to waiting until myService.getContains(idContain) (connected to the api resource) completly finished to load before continuing ?
$resource makes an asynchronous request but immediately reurns an empty object or array.
There are numerous ways you could handle your issue.
One would be not to worry about declaring $scope.containRoot and just using currentContain.contain.containRoot in the view. This property will get rendered after the request is received
Another is to use the $promise that is also returned by $resource and assign the scope property in promise callback
$scope.currentContain = myService.getContains(idContain);
$scope.currentContain.$promise.then(function(){
$scope.containRoot = $scope.currentContain.contain.containRoot;
});
Another is to use a routing resolve based on the same promise so the route( or state depending on router) is noot entered until the request is complete
Inside my Controller I have tried to stop $http being called multiple times, but my efforts seem to be in vein.
I only want the report's items to be loaded once.
Have tried checking for items being undefined and having a timesrun variable at the top of the Controller and increasing by 1 at the bottom of it.
if ($scope.items === undefined && $scope.timesrun == 0)
{
var req = {
method: 'GET',
*snipped*
};
$http(req).success(function (data, status, headers, config) {
$scope.items = data;
}).error(function (data, status, headers, config) {
SweetAlert.swal("Error " + status, data, "error");
});
}
I have even had this in a service but the service just gets called multiple times.
I'm clearly missing a trick. I can understand the digest cycle and I do have expressions in the page that need to be checked so I can see why the controller is running multiple times, but I cannot understand how I can get it to exclude the web calls after they've run once.
Being called $http service twice or more may be due to many reasons. Few I am listing below:
Do not mention controller (see : omit ng-controller='HomePanel' in html) name in template.
If you are using ngRoute, and mentioning controller name in template, as well in route config, it may be calling twice. For example. In app.js
app.config([ '$routeProvider', '$sceProvider',
function($routeProvider, $sceProvider) {
$routeProvider.when('/', {
templateUrl : 'Home',
controller : 'HomePanel',
});
}]);
and in HTML:
<script type="text/ng-template" id="Home">
<div ng-controller="HomePanel">
</div>
</script>
Don't let you ajax call to cache. So append some random value in end of your URL.
var req =
{
method: 'GET',
url : someUrl + "&random="+ Math.random();
};
Hope this may help.
Instead of using $http in controller put it in a function in a custom service and call that function when you want to update data from controller or you can call $http in service and assign it to a variable and use that in controller.
I've seen this and this but it seems like there might be a simpler way.
In my view I have several menu options that are controlled through permissioning - i.e., not everyone can see a "Dashboard" view. So in my menu option in my view I have something like the following:
<li ng-show="validatePermission('Dashboard')">Dashboard</li>
In my controller I have a validatePermission method defined where it is looking at the permissions of the current user. For example:
$scope.validatePermission = function(objectName) {
if $scope.allPermissions......
Also in my controller I'm loading those permissions via an $http call:
$http.get('permissions/' + userid + '.json').success(function(data) {
$scope.allPermissions = data;....
The issue is that $scope.allPermissions doesn't get loaded before the view makes the call to validatePermission. How can I wait for allPermissions to be loaded before the view renders?
You ask:
How can I wait for allPermissions to be loaded before the view renders?
To prevent the entire view from rendering, you must use resolve. You don't have to use the promise library though, since $http returns a promise:
var app = angular.module('app');
app.config(function ($routeProvider) {
$routeProvider
.when('/', {
templateUrl : 'template.html',
controller : 'MyCtrl',
resolve : MyCtrl.resolve
});
});
function MyCtrl ($scope, myHttpResponse) {
// controller logic
}
MyCtrl.resolve = {
myHttpResponse : function($http) {
return $http({
method: 'GET',
url: 'http://example.com'
})
.success(function(data, status) {
// Probably no need to do anything here.
})
.error(function(data, status){
// Maybe add an error message to a service here.
// In this case your $http promise was rejected automatically and the view won't render.
});
}
}
But if you simply want to hide the dashboard <li>, then do as Joe Gauterin suggested. Here's a very simple example plunkr if you need it.
Have the validatedPermission function return false when allPermissions hasn't been loaded. That way the element with your ng-show won't be displayed until allPermissions has been loaded.
Alternatively, put an ng-show="allPermissions" on the enclosing <ul> or <ol>.
You can also specify on your routecontroller a resolve object that will wait for that object to resolve prior to rendering that route.
From the angular docs: https://docs.angularjs.org/api/ngRoute/provider/$routeProvider
resolve - {Object.=} - An optional map of dependencies which should be injected into the controller. If any of these dependencies are promises, they will be resolved and converted to a value before the controller is instantiated and the $routeChangeSuccess event is fired. The map object is:
key – {string}: a name of a dependency to be injected into the controller.
factory - {string|function}: If string then it is an alias for a service. Otherwise if function, then it is injected and the return value is treated as the dependency. If the result is a promise, it is resolved before its value is injected into the controller.
A google group reference as well: https://groups.google.com/forum/#!topic/angular/QtO8QoxSjYw
I encountered an similar situation, you might also want to take a quick look at
http://docs.angularjs.org/api/ng/directive/ngCloak
if you're still seeing a "flicker" effect.
As per the angularjs documentation:
The ngCloak directive is used to prevent the Angular html template from being briefly displayed by the browser in its raw (uncompiled) form while your application is loading. Use this directive to avoid the undesirable flicker effect caused by the html template display.
Wrapping the code in ng-if fixed the issue for me:
<div ng-if="dependentObject">
<!-- code for dependentObject goes here -->
</div>