Change angularjs code to work for jquery pop-up - javascript

Hi I don't know angularJS yet I have a task in that. There is dashboard which is designed in angularJS. Now, in that there is link which will
open a pop-up. I have given a task to change that link to another pop-up but that pop-up is in jQuery. So, for me it is quite difficult to understand how to
change this.
I have a xml file where all the label in html are defined. This is the label from where the link is coming.
<subcolumn type="a" ngclick="decisioncomp();" styleName="proccheader labe1padding" text="Complete : " uniqueID="data31" />
Now, in the controller file of the same there is a function defined.
// complete link click
$scope.decisioncomp = function () {
if ($scope.data31 != "") {
ModalService.showModal({
templateUrl: "ChartpagePopup/Complete.html",
controller: "Complete"
}).then(function (modal) {
modal.close.then(function (result) {
$scope.customResult = "All good!";
});
});
}
else
alert($scope.waitingalert);
};
So, I came to know from here the link is going to html and controller. Now, I thought that if changed this ModalService.showModal to not to take controller
or if I send controller empty and replace my html with this html, my work should be done. So what I did is I changed in the Script file for that where this
funtion is defined.
I commented out line where it says that controller can't be empty.
self.showModal = function(options) {
// Create a deferred we'll resolve when the modal is ready.
var deferred = $q.defer();
// Validate the input parameters.
var controllerName = options.controller;
if (!controllerName) {
//deferred.reject("No controller has been specified.");
//return deferred.promise;
}
But then the link itself is not opening. I don't know where else to change. I am stuck here. Please someone help me.

Related

Add Content To DOM AFTER AngularJS Has Completed Asynchronous Loading

I have angular code that fetches 8 json files asynchronously each via $http.get. This is called using ng-init="someFunct()" in a template code that is attached. Everything works great including filtering when a user types into an input text box. Filtering is especially important to my application.
To make filtering even better, I extract keywords from the said json files which I then wrap with <span class="tag" ng-click="filterWith='kywd'">{{kywd}}</span> in the hope that a user can click on the tags instead of type. This ONLY works if I embed the tags statically - in the real application I cannot know the keywords in advance. If I insert dynamically via $("#someContainerID").append(TAG_HTML_CODE) or similar it NEVER works!
In a nutshell this is what I need to achieve:
1) Dynamically inject multiple (in hundreds) such tags into DOM;
2) Inject the tags ONLY after everything else has loaded and compiled - but especially after the json files have been read and keywords extracted;
3) The tags that I inject need to respond to something like ng-click="filterWith='some_keyword'"
If there was a way to tell when AngularJS has finished all other processing - how great this would be! I have read everywhere and it seems so cryptic and confusing - pls HELP!
I have even tried the following code to no avail:
$timeout(function () {
$scope.$apply(function () {
//code that works on the keywords - works perfect!
var filterRegex = /\s*([\w\d.%]+)\s*/i;
var dom_elem = angular.element(document.querySelector("#filter_tags"));
dom_elem.html("");
for (var m = 0; m < tags.length; m += 1) {
var match = filterRegex.exec(tags[m][0]);
if (match != null) {
dom_elem.append($compile("<span data-ng-model=\"filterWith\" data-ng-click=\"filterWith='" + match[1] + "'\" title=\"" + tags[m][1] + "\" class=\"sk3tag clk\">" + match[1] + "</span>")($scope));
}
}
});
}, 10000, false);
}
EDIT: Narrowed the scope of my challenge to mainly one!
The bigger challenge for me is how to enable ng-click in the dynamically injected code and how to do it right.
Use Promise.all() to trigger when everything is loaded.
Earlier I had asked the question above. Somebody suggested I read further on directives instead. I did, fairly well. I came up with the following solution, to use click events on html code injected dynamically to DOM. I thank truly God for helping me figure it out, eventually. I no longer need to wait for the asynch data, whenever it comes and hence updates the model, my html tags are updated automatically - MVC magic! It seems to work great!
ANGULAR
//excerpt
myNgApp.controller('ctlTodayLatest', ['$scope', '$timeout', '$compile', '$http', function () {
$http.get('/filtertags.json').then(function (response) {
$scope.filterTags = response;
},
function (response) {
// called asynchronously if an error occurs
// or server returns response with an error status.
console.log(response);
}
);
}]);
myNgApp.directive("myFilterTag", function () {
return {
template: "<span data-ng-repeat=\"tag in filterTags\" title=\"{{tag[0]}}\" class=\"mytag clk\" ng-click=\"filterWith(tag[0])\">{{tag[0]}}</span>",
link: function (scope, element, attrs) {
scope.filterWith = function (term) {
scope.fQ = term;
};
}
};
});
HTML
//excerpt
<div id="filter_tags" class="xip2 TAj" my-filter-tag></div>

AngularJS UI router's "resolve" fires twice

I am using angular ui router to handle some routing on my frontend. This is what my routing code looks like.
// angular config
$stateProvider.state('app', {
templateUrl: '/static/partials/home.html',
controller: 'NavCtrl'
});
$stateProvider.state('app.reader', {
url : '/reader/*path?start&end&column&page',
templateUrl: '/static/partials/reader.html',
resolve : {
panelContent : [
'$state', '$stateParams', '$http',
function ($state, $stateParams, $http) {
alert('resolving panel Content');
return []; // simplest thing possible to illustrate my point
}
]
},
controller: 'ReaderCtrl'
});
/// etc etc
$urlRouterProvider.otherwise('/reader/');
My html makes use of multiple nested views, I'll try and illustrate as best I can
index.html
<html>
<div ui-view></div> <!-- /static/partials/home.html gets injected here -->
</html>
/static/home.html
<html>
<!-- some side bar stuff -->
<!-- reader -->
<div ui-view></div> <!-- /static/partials/reader.html gets injected here -->
</html>
So I've got multiple levels of nesting going on
-- index.html
-- home.html
-- reader.html
Now, when I load the page for the first time, my alert message
alert('resolving panel Content');
fires just once.. that makes sense. However, let's say I click "next page" inside my pagination..
<!-- inside /static/partials/reader.html -->
<uib
pagination total-items= "totalItems"
ng-model= "pageNumber"
ng-change= "pageUpdate"
max-size= "maxPageNumbersDisplayed"
></uib>
this eventually fires a function inside my "ReaderCtrl"
$scope.pageUpdate(page) {
$state.go( '.', {page: page});
}
This updates the url, from going to something like this
/#/reader/<my path>
to something like this
/#/reader/<my_path>?page=2
Now for the part that has me tearing my hair out.
I get back to the "resolve" code block in the reader section of my routing.
The alert message happens twice.
By doing a bit of debugging in the web console, I discovered that the order goes
1) alert message in resolve
2) travel through the entirety of ReaderCtrl
3) lots and lots of angular calls
4) alert message (2nd time)
5) travel through entirety of ReaderCtrl a second time.
You might be inclined to know what is going on in NavCtrl, but I am not making any calls there. All that is in NavCtrl are functions that ReaderCtrl can inherit, in order to update the scope for /static/partials/home.html
So really, it appears as though I am stuck on step 3 here.
Does anyone have any ideas as to why my resolve block appears to be firing twice?
edit:
after a bit more debugging, I have seemed to figure out that the order goes something like this, starting right after the "updatePage" function executes.
1) first "resolving message"
-- the url has not yet changed
2) second "resolving message"
-- the url appears to have changed very shortly before this message
So, I guess my question now is...
why does
$state.go('.', args);
NOT change the url before the first alert fires, but DOES change the url at/near the second alert?
edit 2: could not end up fixing my issue, so I sort of hacked around it for the time being... I essentially made a function that did what I assume $state.go() was doing behind the scenes, and constructed the url.
function _mk_url(args) {
var url = "/reader";
var pageNumber = args.pageNumber || 1;
url += "?page=" + pageNumber;
var columns = args.columns || [];
columns.forEach(function(d) {
url += "&column=" + d;
});
//etc..
return url;
}
var args = {"columns" : ["a", "b", "c"], "pageNumber" : 2};
var url = _mk_url(args);
$location.url(url);
I was having this problem and found out it was because I was calling my resolve function manually somewhere else in the code. Search your code for panelContent() and you may find where it's getting triggered again.
I'd got this problem. The reason was in my html template. I used ui-sref directive in both child and parent elements
<li ui-sref="{{r.name}}" ng-class="vm.isCurrent(r)" ng-repeat="r in vm.settingsRoutes">
<span ui-sref="{{r.name}}" ng-bind-html="r.title"></span>
</li>
so when I clicked on span, I fired stateChange twice.
I've had the same bug.
And I found that I was changed $stateParams in one of the resolve functions.
The solution is make a copy from this object and then do what you want with a copy.
resolve: {
/** #ngInject */
searchParams: function ($stateParams) {
let params = angular.copy($stateParams); // good
// good:
if (params.pending === undefined) {
params.pending = true;
}
// bad:
if ($stateParams.redirect === 'true') {
$stateParams.pending = false; // this line changing the URL
}
return params;
},
}

AngularJS Controller executing before template loads

I have a email verification link, which looks something like
.when('/user/register/verify/:verify_code?', {
controller: 'AngularRegisterVerifyPage',
templateUrl: '/user/register/verify'
})
And my input field is like this.
input(ng-model="formData.verify_code", name="verify_code", type='text', class='form-control', placeholder='Verification Code', id="verify_code")
And this code should run when the template loads to insert the Parameter into the text field
document.getElementById('verify_code').value = "Test"; // Debugging Test Code
$scope.formSubmitted = false;
if ($routeParams.hasOwnProperty("verify_code")) {
document.getElementById('verify_code').value = $routeParams.verify_code;
}
But it would appear that the controller executes this before the template actually loads because when the page loads the input field is empty. Any information on how to do this properly would be great, I tried googling things like "Load Template after Controller loads" but haven't found anything. Thanks.
Edit:
I tried adding ng-init="loadCode()" to the input field, but it still doesn't work.
$scope.loadCode = function() {
if ($routeParams.hasOwnProperty("verify_code")) {
console.log('Called');
document.getElementById('verify_code').value = $routeParams.verify_code;
console.log($routeParams.verify_code);
console.log(document.getElementById('verify_code').value);
}
}
You don't need to change input value by manupulate dom in angularjs. Angular already has a lot of tremendous mechanism to help you reduce your development work.
In your case, you just change your code into this:
.controller('AngularRegisterVerifyPage', function($scope, $routeParams){
$scope.formData = {};
if ($routeParams.hasOwnProperty("verify_code")) {
//You change your value in your model, angular will render this to your html(view)
$scope.formData.verify_code = $routeParams.verify_code;
}
});
Here is a useful answer for angular newer: “Thinking in AngularJS” if I have a jQuery background?
Here is ngModel Document.
Enjoy it : )

AngularJS - Refresh after POST

What is the correct way to refresh content after a http POST request in Angular?
//controller.js
var hudControllers = angular.module('hudControllers', []);
hudControllers.controller('PropertyDetailsCtrl',
['$scope','$window','$http', function ($scope,$window,$http) {
//I want to reload this once the newCommentForm below has been submitted
$http.get('/api/comments')
.success(function(data) {$scope.comments = {"data":data};}})
.error(function(data) {...);
$scope.newCommentForm = function(){
newComment=$scope.newComment;
requestUrl='/api/comments';
var request = $http({method: "post",url: requestUrl,data: {...}});
request.success(function(){
//How do I refresh/reload the comments?
$scope.comments.push({'comment':'test'}); //Returns error - "TypeError: undefined is not a function"
});
};
}]);
//template.ejs
<div class="comment">
<ul>
<li ng-repeat="comment in comments.data">{{comment.comment}}</li>
</ul>
</div>
Thanks.
There are many ways you can do it. still I want to show you simplest way (according to your needs).
lets say you have 'first.html' page and 'PropertyDetailsCtrl' is associated with it.
Now, in html you can write like this,
with very first-div
<div ng-controller="PropertyDetailsCtrl" ng-init="initFirst()">
.... Your page contents...
</div> (This will initialize your controller and you will have execution of your first method 'initFirst()'.
at your .js side....
var hudControllers = angular.module('hudControllers', []);
hudControllers.controller('PropertyDetailsCtrl',
['$scope','$window','$http', function ($scope,$window,$http) {
//I want to reload this once the newCommentForm below has been submitted
$scope.initFirst=function()
{
$http.get('/api/comments')
.success(function(data) {...})
.error(function(data) {...);
//You need to define your required $scope.....
$scope.myVariable=data;
};
Now at appropriate time (You know when) your below method gets called.
$scope.newCommentForm = function(){
newComment=$scope.newComment;
requestUrl='/api/comments';
var request = $http({method: "post",url: requestUrl,data: {...}});
request.success(function(data){
//How do I refresh/reload the comments?
//without calling anything else, you can update your $scope.myVariable here directly like this
$scope.myVariable=data
});
//or else you can call 'initFirst()' method whenever and wherever needed like this,
$scope.initFirst();
};
}]);
I hope this will help.
Not sure if there is ONE correct way, but you can call $location.path() on success.
request.success(function(){
$location.path('your path');
});
To view the added comment (which apparently is what you want), you could use :
request.success(function(response){
$scope.comments.push(response.data);
});
Your content would refresh automatically on the page, if you're using angular expressions and a ng-repeat.

$location does not navigate on first ng-click callback

Something weird is going on in my AngularJS application. I have a view which has a list of anchor tags bound to an array of objects (I'm using ng-repeat to render the list). Each one of the anchor tag has an ng-click bound to a method on the controller. The method is as follows:
$scope.onSiteSelected = function ($event, site) {
$event.preventDefault();
$.ajax({
url: '/Site/GetSiteMap/' + site.Id,
success: function (response) {
if (response && response.length > 0) {
menuManager.setSiteMap($scope.$root.menu, response[0]);
var url = response[0].Children[0].Settings.Url;
$location.path(url);
}
}
});
}
The url var is being initialized to the correct value every time. But, when I click on the anchor tag the first time, $location.path(url) does nothing, and when I click it for a second time, it does navigate to the target url.
UPDATE:
Ok I got it working by using the $http service as follows:
$scope.onSiteSelected = function ($event, site) {
$event.preventDefault();
var address = '/Site/GetSiteMap/' + site.Id;
$http.get(address)
.success(function (response) {
if (response && response.length > 0) {
menuManager.setSiteMap($scope.$root.menu, response[0]);
var url = response[0].Children[2].Settings.Url;
$location.path(url);
}
});
}
Does it really make a difference if I used $,ajax or $http? I thought the two can be used interchangeably...?
No you cannot use them interchangibly, $.ajax is jQuery whereas $http is angular's http service.
Resist the urge to use jQuery as there is almost always a way to do it in the angular way.
That being said, if you do something outside of angular world, (mostly callbacks didn't occur from angular), you need to apply the changes to force a digest cycle.
$.doSth(function callback() {
$scope.$apply(function () {
// your actual code
});
});
Please read the most voted answer in "Thinking in AngularJS" if I have a jQuery background? . This would guide you to avoid using jQuery where there is an alternative.

Categories