AngularJS adds extra & - angularjs

I want to pass a stringified JSON as an argument but Angular keeps adding extra & at the end of my query. Which is causing me headache.
Here is how I call it:
$scope.products = ProductSvc.getProductsList('{branchId:{"$exists":"true"}}');
which in turn calls:
ProductRes.q({'queryStr':params});
And here is how q is defined:
var ProductRes = $resource('/products/:productId',
{ 'productId':'#productId','queryStr':'#query' },
{
'$save':{method:'POST', params:{'productId':'#productId'}, isArray:true},
'$get':{method:'GET', params:{'productId':'#productId'}},
'q':{method:'GET', isArray:true, url:'/products?:queryStr'},
'$query':{method:'GET', isArray:true, url:'/products'},
}
);
So the problem is, angularJS GETs:
/products?{branchId:{"$exists":true}}& // <- This goddamn ampersand!!
And that extra ampersand is causing my backend to misbehave.
How to get rid of it?

Related

Why would the ASP.NET MVC HttpFileCollection return an array of strings rather than a Collection of HttpPostedFile?

I have an AngularJS + ASP.NET MVC 5 application where I am attempting to implement single file uploading.
On the client side I have the following code:
api.uploadFileV2 = function (alias, file, fnSuccess, fnError) {
var formData = new FormData();
formData.append(file.name, file);
$http.post('/api/V2/Upload/' + alias, formData, {
transformRequest: angular.identity,
headers: { 'Content-Type': undefined }
}).success(function (data) {
if (fnSuccess)
fnSuccess(data);
}).error(function (data) {
if (fnError)
fnError(data);
});
}
The file parameter is passed in from a function invoked by a button click and when executing in Chrome and in Edge I can see that the file parameter is in fact a file object.
Back on the server side I have a route to a controller defined as follows:
config.Routes.MapHttpRoute(
name: "V2UploadApi",
routeTemplate: "api/V2/Upload/{alias}/{id}",
defaults: new { controller = "Upload", id = RouteParameter.Optional }
);
Back on the server side I have my UploadController in which I have the following method defined:
public JArray Upload(string Alias)
{
JArray results = new JArray();
try
{
HttpRequest r = HttpContext.Current.Request;
HttpFileCollection c = r.Files;
foreach (var item in r.Files)
{
string theType = item.GetType().Name;
}
}
...
}
NOTE: The reason for the odd method signature with the Alias parameter is that ultimately the uploaded file will be managed by a Powershell script the selection and security level of which depends on the alias value.
Upon execution of the UploadController.Upload method I see the Alias value I'm expecting.
I do not see my file object. So var item does not resolve to the type HttpPostedFile as I expect but instead it resolves to a string type and so the variable "theType" contains "string" and not "HttpPostedFile". The HttpFileCollection doesn't actually contain a collection of HttpPostedFile objects and attempting cast the items in the collection results to the type HttpPostedFile results in an exception being thrown.
What could be causing this bizarre behavior on the server side and what can I do o correct it?
Something as basic as uploading a file should not be this difficult so I must be missing something obvious - trouble is I'm not seeing it.
So after another debugging session I altered the code to:
HttpRequest r = HttpContext.Current.Request;
HttpFileCollection c = r.Files;
foreach (string key in r.Files.Keys)
{
var item = r.Files[key];
string theType = item.GetType().Name;
}
This code not only works but also appeals to my old fashioned coding style of NOT lazily leaving absolutely everything up to the compiler using var. I wrongly assumed the enumerator of the HttpFileCollection to return (string)Key/(HttpPostedFile)Value pairs but I was wrong.

javascript evaluation failed- karate

I am trying to call an API in second feature file , passing arguments from first feature file . These has to be passed as a param for second API
* def activeDetails =
"""
function(times){
for(i=0;i<=times;i++){
karate.log('Run test round: '+(i+1));
karate.call('getActiveRouteDetails.feature', { token: token, currentPage: i });
}
java.lang.Thread.sleep(1*1000);
}
"""
* call activeDetails totalPages
In my second feature , I am able to print the values passed , Getting error while passing it as a param 'no step-definition method match found for: param pageNumber'
And print currentPage
And print token
And param pageNumber = '#currentPage'
And param token = token
Watch the white space around the = sign. Normally if you use IDE support you can avoid these issues. You seem to have an extra space after pageNumber.
So make this change:
And param pageNumber = currentPage
I request you to please read the docs and examples. You are still un-necessarily making 2 calls. And over complicating your test.

Assign a dynamic value to object from json

I've built a panorama viewer using Pannellum, where I pass options into the default config to generate a view like so;
var panoOptionDefaults = {
type: "equirectangular",
haov: imageXRes,
vaov :imageYRes,
minPitch : 0,
maxPitch : 0,
minYaw : (imageYRes * 2) * -1,
maxYaw : (imageYRes * 2),
autoLoad : true,
mouseZoom : false,
showControls : false,
hfov:imageXRes * 2, // Zoom - positive number zooms out / negative number zooms in
panorama: $scope.currentProfile.panorama.image, //value in json, returns error
hotSpotDebug : false,
hotSpots: [ // Dynamic Value
{
"pitch": -9.0,
"yaw": -1.0,
"cssClass": "custom-hotspot",
"createTooltipFunc": hotspot,
"createTooltipArgs": "Radios for Communication"
}
]
}
What I'm trying to do is have the value of 'panaroma' come through from my response.data Get method. I've already written a working angular service that returns a profile.json based on an attribute and a get method that returns this json result for each directive that has individual data here ;
$scope.currentProfile = {}; / /creates object
profiles.getProfile().then(function(response){
$scope.currentProfile = response.data; //returns data and assigns to $scope
});
It's a little difficult to be sure since your answer in still lacking some key details (like when are you using the panoOptionsDefault object), but I suspect that your issue is due to the asynchronous nature of JavaScript.
The comment on the line that assigns panorama says "returns error", but you don't specify the error message. I suspect that error is occurring because the value of $scope.currentProfile has not been assigned yet. If so, you need to wait until the AJAX call that retrieves that data is complete before you use panoOptionsDefault.
So you need to do something like this:
profiles.getProfile().then(function(response){
$scope.currentProfile = response.data;
// Now you can use panoOptionsDefault
SomeCall(panoOptionsDefault);
});

ngModel and resetting value

So have two directives that need to share data. Both are under the same controller, so set up the variable $scope.selection to store the selection, it gets a default value in the controller.
knowledge.controller('industryController', function($scope, mwFactory){
$scope.menudata={sections: [
{group: 'FMP', name: 'Finance'},
{group: 'FinTech', name: 'Financial Technology'},
]
}
if ($scope.selection) {
console.log("This is " + $scope.selection)
} else {
$scope.selection = 'Main_Page'
}
})
I then send that to a menu where you can make selection
<nav-circle group="section.group" ng-model="selection"></nav-circle>
I then set it as follows inside the directive
function nodeclick(d){
//console.log("Name is " + d.url);
console.log("Old model is " + ngModel.$modelValue)
ngModel.$modelValue = d.url;
ngModel.$viewValue = d.url;
console.log("New model is " + ngModel.$modelValue)
}
However, it does not seem like it is updating, or potentially even weirder, that something is resetting ngModel.
Got a call further up,
ngModel.$render = function () {
console.log("ngRender got called " + ngModel.$modelValue);
};
And this kicks off every minute or so, and always returns the value to the original value. What am I missing
OK, this may not be the best way, but it works, and sometimes that is enough:)
Instead of sending a variable I sent an object, and I think (someone who knows angular and javascript better may be able to explain/confirm) this means that the directive will be writing to a memory address rather than to a variable. Which also means that the ng-model will not change (the memory address is the same, the data stored at that memory address is changed).
Might be wrong, but the solution works as if that was the case.
So, define the scope variable:
$scope.selection = {};
$scope.selection.default = 'Main_Page'
$scope.selection.current = '';
Then send the following to the directives:
<nav-circle group="section.group" ng-model="selection.current"></nav-circle>
And to change the scope variable in the directive you just set viewValue
ngModel.$setViewValue(d.url);
As I mentioned, I am not certain if this is the right way, or if my understanding is correct, but it works:)

AngularJS e2e Testing: How To Get value of repeater().count()?

Problem
Calling repeater('#myTable tr','Rows').count(); returns a Future, not an integer. I need to get the integer value so I can confirm that an additional row was added to a table.
Code
it('should add a new user when save button is clicked',function()
{
showModal();
//here I'm trynig to store the row count of my table into a local variable.
//a future is returned who's 'value' field is undefined.
var memberCount = repeater('#memberTable tr','Member Rows').count();
//this outputs 'undefined'
console.log(memberCount.value);
input('editedMember.name').enter('John');
input('editedMember.grade').enter(5);
input('editedMember.ladderPosition').enter(3);
element('#saveMemberButton').click();
sleep(1);
expect(element(modalId).css('display')).toBe('none');
//here is where I want to do the comparison against the above stored memberCount
expect(repeater('#memberTable tr', 'Member Rows').count()).toBe(memberCount.value + 1);
});
Test Result
Chrome 25.0 e2e should add a new user when save button is clicked FAILED
expect repeater 'Member Rows ( #memberTable tr )' count toBe null
/Users/jgordon/learning/chessClub/web-app/test/e2e/scenarios.js:45:3: expected null but was 6
Chrome 25.0: Executed 2 of 2 (1 FAILED) (1 min 4.117 secs / 1 min 3.773 secs)
Drilling into the source code for Angularjs' e2e support reveals that you have to call execute() on the Future to have it populate its value. Also, when you call execute you have to provide a "done" function to the execute() otherwise Testacular will (oddly enough!) skip your test.
Code
var rowCountFuture = repeater('#memberTable tr','Member Rows').count();
rowCountFuture.execute(function(){
});
var memberCount = rowCountFuture.value;
While I'm jazzed to see this works, I'm concerned there may be some asynchronous bugs that could come out of this, also, I feel like this is a hack and not the right way to do it. Any ideas?
Based on the latest Protractor version:
it('should add a new user when save button is clicked', function() {
var memberCount;
element.all(by.repeater('#memberTable tr','Member Rows')).count().then(function(value) {
memberCount = value;
});
...
// then do all your entering user info, saving etc.
...
browser.refresh(); // or however you want to load new data
expect(element.all(by.repeater('#memberTable tr','Member Rows')).count()).toEqual(memberCount + 1);
});
I've run into the same issue, and have seen confusing results when testing value returned after calling execute(). I've found this method works more reliably:
var getCount = repeater('ul li').count();
getCount.execute(function(value) {
expect(value).toEqual(3);
});
You can do this most easily in the async promise returned by the locator
element.all(By.repeater 'thing in things').then(function(elements){
count = elements.length;
expect(count).toEqual(3);
});

Resources