In our current project we started using angularjs.
We're facing the choice to either use == rather then === everywhere or specifically parse query parameters to their respective correct type.
Hypothetical example:
//someurl.com/search?filter=astring&sortColumn=2
$scope.filter = $location.search().filter;
$scope.sortColumn = $location.search().sortColumn;
if($scope.sortColumn === 2){
doStuff();
}
Because sortColumn comes out of the querystring as a string, the strict equation fails.
I think it comes down to either use non-strict equation or parse strings to ints.
Currently we have a stringToInt() that uses parseInt() with some extra checks on null and undefined, but this feels like we're trying to write C# in js to me.
Can we get ints from search() somehow?
Or should we switch to non-strict in our equations?
Or is there another way we didn't think of?
Related
This question already has answers here:
How to define a regex-matched string type in Typescript?
(9 answers)
Closed 2 years ago.
I am wondering if there is a way to create types that are verified by a function in Typescript/React.
Instead of a 'string' type for example, I would like it to be a regex expression:
interface Verify
{
email: /.+#.*\.com/g;
}
The regex may not work but the concept is of a prop type being a string matching the regex.
A more generalized and useful is to have the input pass through a function to verify it:
interface AcceptableInput
{
input: checkIfInputIsAcceptable(input)
}
let obj: AcceptableInput = { input: "works#working.com" }
Then to check if the input is of the correct type it would check with a function:
function checkIfInputIsAcceptable(input)
{
if(typeof input === "string)
return true;
if(input instanceof AnotherInterface)
return true;
return false;
}
The code does not work, but I hope it exemplifies the concept I am asking about.
I am not sure if this is possible. Any workarounds would also be appreciated.
TypeScript won't really do any complex validation because it's fairly pointless (because you can solve the same issue in different ways, see below) and it heavily complicates the type system. The best way to do something like this is probably via type guards and runtime validation code. (see https://www.typescriptlang.org/docs/handbook/advanced-types.html)
If you're matching against a very basic string pattern then you could also consider looking into template literal types which were added in Typescript 4.1 (see https://www.typescriptlang.org/docs/handbook/2/template-literal-types.html)
I have a complex odata query that I am passing through Angular using OdataAngularResrouce library. As we all know that odata queries are case sensitive and obviously I dont know how the data is being stored in the database. Here is the predicates that I used to build the query.
var predicFirstName = new $odata.Predicate(new $odata.Func("startswith", "FirstName", new $odata.Func("tolower", $scope.searchObject.searchString)), true);
var predicLastName = new $odata.Predicate(new $odata.Func("startswith", "LastName", new $odata.Func("tolower", $scope.searchObject.searchString)));
**OData URI:**
https://localhost/app/TylerIdentityUserAdministrationService/Users/$count/?$filter=((startswith(FirstName,tolower(Fahad)))%20or%20startswith(LastName,tolower(Fahad)))
As you can see, I want to put a function to check only the given string with startswith. I have seen several posts where the solution is to put the tolower(). However, when I put it the way mentioned above its not returning any data. Can anybody help here?
Thanks
-Fahad
Both the properties and the literal strings in the $filter need to be converted to lowercase. And since the literal strings originate on the client, you can optimize by converting them to lowercase before you send the OData request.
$filter=startswith(tolower(FirstName),'fahad') or startswith(tolower(LastName),'fahad')
Note that the literal strings must be surrounded with single quotes in the filter expression.
I changed my handlebar template's extension and referred to the same in the function which called handlebarjs' compile function.
It worked perfectly fine with no issues.
But I'm curious to know if anyone else tried that?
Please let me know if you think this could cause problems down the road for any reason.
For some reason I feel that the very extension .handlebars is a bit long. I prefer to keep it to a max of 4 chars ... something like .txt or .html.
Please let me know if you see any issues with this approach.
For example, I renamed login.handlebars to login.html
In the getTemplate function (as shown below), I will call this template for compilation
function getTemplate(name) {
if (Handlebars.templates === undefined || Handlebars.templates[name] === undefined) {
$.ajax({
url : "templates/" + name + ".html",
success : function(data) {
if (Handlebars.templates === undefined) {
Handlebars.templates = {};
}
Handlebars.templates[name] = Handlebars.compile(data);
},
async : false
});
}
return Handlebars.templates[name];
}
My shop uses .handlebars, along with Require.js and Alex Sexton's require-handlebars plug-in, and it all works without issue. The far more common suffix however, and the default one in that plug-in I just mentioned, is .hbs (presumably because .hbs is a 3-character extension not already taken by another file type).
You can for example use .hbs, .handlebars, or even a different extension for that matter, and it should work just fine with any sort of library (eg. Require) where the suffix could actually matter. There are no guarantees of course, but because there is no official extension library authors generally know better than to hard-code one.
I would caution against using .htm or .html for these files though ... unless you have a really picky IDE. Most IDEs can be set to treat .hbs as if it were an HTML files, for syntax coloring and what not. If your's can't, then .htm might make sense. Otherwise I'd keep the file extension distinct, so that you can easily distinguish between the two types of files.
I have this error that doesnt give any indication as to what is the problem:
I'm trying to store this string in lesson_location field:
B^$eNrT0srLywNiLRANpiAsMAknoMKognlwdUi6ERrQuDARmCwmE2EMslOQ9aFaguw6dKyllQxhJcNp TFBTk1iSWhBvYBhvYGAKABXXVRId;
but it throws SyntaxError: unterminated string literal
when I've modified the way the reload stores the data in ReloadAPIAdaptor.js
from using eval on entire string:
eval("this.cmi.core.lesson_location.cmivalue =\"B^$eNrT0srLywNiLRANpiAsMAknoMKognlwdUi6ERrQuDARmCwmE2EMslOQ9aFaguw6dAzXnJwMozFB TU1ual4pAMimU3Qd;\";");
to evaluate object first:
var o = eval("this." + element);
console.log("o",o);
if(o) o.cmivalue = value;
then it stores data without error,
now I can't modify the code in any lms so this was only to identify if the string can't be stored but it can. Just evil doesnt work so the question is what is in the given string that eval doesnt like and how to fix it.
There is nothing wrong with your string if you're doing the following:
API.SetValue("cmi.core.lesson_location", "B^$eNrT0srLywNiLRANpiAsMAknoMKognlwdUi6ERrQuDARmCwmE2EMslOQ9aFaguw6dKyllQxhJcNp TFBTk1iSWhBvYBhvYGAKABXXVRId;");
(where API is a reference to the window's API object)
The string is valid as far as SCORM is concerned, and the length falls within the acceptable character limit.
If you're encountering an issue, it might be a bug within the Reload wrapper. Frankly, the code in the Reload wrapper (as found on SourceForge) is TEN years old. It uses eval() and other JavaScript techniques that have been identified as problematic, and are highly discouraged by leading JavaScript developers. Your bug might very well be related to the wrapper's use of eval().
I'd try using a different wrapper and see if it makes a difference.
I'm currently trying to figure out if there is a way to do a simple future/past comparison ex.
1) Check state of list by getting list length
2) Perform action which if success increments the list
3) Compare the current list length to the past.
But the concepts of Futures seems to get in my way. One would think this is a pretty normal use case.
Q: How would you go about handling past/future comparisons in Angularjs Scenario?
It's kind of longwinded, but you can define custom matchers which understand futures. For example:
angular.scenario.matcher('toBeGreaterThanFuture', function(future) {
return +this.actual > +future.value;
});
Use like:
listLengthBefore = repeater('.td').count();
// Do some stuff.
listLengthAfter = repeater('.td').count();
expect(listLengthAfter).toBeGreaterThanFuture(listLengthBefore);