I have save path in database, when I use it in view
#for(photo <- photos){
<img src="#routes.Assets.versioned("images/photo.getPath()")" class="img-rounded" alt="Cinque Terre" width="304" height="236">
}
photo.getPath() is not working, I try with #photo.getPath() still not working. Any suggest for me. I use play-java version 2.5. Thank a lot.
Personally, I find the Twirl syntax a bit unintuitive. The # marks the start of a scala statement. The length of this statement is determined automatically.
Now looking at the img tag:
<img src="#routes.Assets.versioned("images/photo.getPath()")" class="img-rounded" alt="Cinque Terre" width="304" height="236">
the following piece of code should be identified as a single statement:
routes.Assets.versioned("images/photo.getPath()")
From a scala point of view, the "images/photo.getPath()" is just a String. It will not execute any method on the photo object. I think (I didn't test this) that your issue should be solveable by replacing this part by s"images/${photo.getPath()}". Note that the string interpolation will make sure that the method on the photo object will be called.
This would make your example look like:
#for(photo <- photos) {
<img src="#routes.Assets.versioned(s"images/${photo.getPath()}")" class="img-rounded" alt="Cinque Terre" width="304" height="236">
}
Related
Firstly, Karate UI automation is really awesome tool. I am kind of enjoying it while writing the UI tests using Karate. I ran into a situation where in, i was trying to fetch the shadowRoot elements. I read few similar posts related to javascript executor with karate and learnt that it is already answered. it is recommended to use driver.eval. But in Karate 0.9.5 there is no eval, it has script() or scriptAll(). I have gone through documentation couple of times to figure out how i can fetch element inside an element but no luck.
Using traditional selenium+java, we can fetch shadowRoot like this way:
something like shadowRoot which sits inside a parent element like div or body.
//downloads-manager is the tagname and under that downloads-manager, a shadowRoot element exists
The HTML looks like this. it is from chrome://downloads.
<downloads-manager>
#shadow-root(open)
</download-manager>
WebElement downloadManager =driver.findElement(By.tagName("downloads-manager");
WebElement shadowRoot= (WebElement)((JavaScriptExecutor)driver)
.executeScript("return arguments[0].shadowRoot",downloadManager);
So i tried the following in Karate UI
script("downloads-manager","return _.shadowRoot"); //js injection error
script('downloads-manager', "function(e){ return e.shadowRoot;}"); // same injection error as mentioned above.
def shadowRoot = locate("downloads-manager").script("function(e){return e.shadowRoot};"); //returns an empty string.
I bet there is a way to get this shadowRoot element using Karate UI but i am kind of running out of options and not able to figure out this.
Can someone please look into this & help me?
-San
Can you switch to XPath and see if that helps:
* def temp = script('//downloads-manager', '_.innerHTML')
Else please submit a sample in this format so we can debug: https://github.com/intuit/karate/tree/develop/examples/ui-test
EDIT: after you posted the link to that hangouts example in the comments, I figured out the JS that would work:
* driver 'http://html5-demos.appspot.com/hangouts'
* waitFor('#hangouts')
* def heading = script('hangout-module', "_.shadowRoot.querySelector('h1').textContent")
* match heading == 'Paul Irish'
It took some trial and error and fiddling with the DevTools console to figure this out. So the good news is that it is possible, you can use any JS you need, and you do need to know which HTML element to call .shadowRoot on.
EDIT: for other examples of JS in Karate: https://stackoverflow.com/a/60800181/143475
I have added a custom locator in protractor, below is the code
const customLocaterFunc = function (locater: string, parentElement?: Element, rootSelector?: any) {
var using = parentElement || (rootSelector && document.querySelector(rootSelector)) || document;
return using.querySelector("[custom-locater='" + locater + "']");
}
by.addLocator('customLocater', customLocaterFunc);
And then, I have configured it inside protractor.conf.js file, in onPrepare method like this:
...
onPrepare() {
require('./path-to-above-file/');
...
}
...
When I run my tests on the localhost, using browser.get('http://localhost:4200/login'), the custom locator function works absolutely fine. But when I use browser.get('http://11.15.10.111/login'), the same code fails to locate the element.
Please note, that the test runs, the browser gets open, user input gets provided, the user gets logged-in successfully as well, but the element which is referred via this custom locator is not found.
FYI, 11.15.10.111 is the remote machine (a virtual machine) where the application is deployed. So, in short the custom locator works as expected on localhost, but fails on production.
Not an answer, but something you'll want to consider.
I remember adding this custom locator, and encounter some problems with it and realised it's just an attribute name... nothing fancy, so I thought it's actually much faster to write
let elem = $('[custom-locator="locator"]')
which is equivalent to
let elem = element(by.css('[custom-locator="locator"]'))
than
let elem = element(by.customLocator('locator'))
And I gave up on this idea. So maybe you'll want to go this way too
I was able to find a solution to this problem, I used data- prefix for the custom attribute in the HTML. Using which I can find that custom attribute on the production build as well.
This is an HTML5 principle to prepend data- for any custom attribute.
Apart from this, another mistake that I was doing, is with the selector's name. In my code, the selector name is in camelCase (loginBtn), but in the production build, it was replaced with loginbtn (all small case), that's why my custom locater was not able to find it on the production build.
I'm working on a sample app for Facebook, using Flash Builder and Flex.
Now, I've got everything up and running - but there's one problem, specifically with the work history part.
When I try to display the user's work history..here's the code for logging in:
protected function login():void
{
FacebookDesktop.login(loginHandler, ["user_birthday", "user_work_history"]);
}
Here, loginHandler's a callback function, that then goes ahead and displays data about the user:
protected function loginHandler(success:Object,fail:Object):void
{
if (success){
currentState = "LoggedIn";
fname.text = success.user.name;
userImg.source=FacebookDesktop.getImageUrl(success.uid,"small");
birthdayLbl.text=success.user.birthday;
workLbl.text=success.user.work;
}
}
Now, the problem occurs with success.user.work - it ends up printing the following:
[object,Object],[object,Object],[object,Object],[object,Object]
Obviously, I'm doing something wrong..but I can't figure out what exactly it is. Would be grateful for some pointers!
Thanks!
Rudi.
The object contained in success.user.work is most likely an array of objects, each item representing a work period, so you'll have to treat it as such. Either use a list and a custom renderer for each item, or create a string by iterating over the array, and appending the fields that you're interested in.
To see what the individual objects contain, either use a breakpoint during debug and inspect them, or check to see if they're documented in the facebook development documentation.
I'm looking specifically for a way to automatically hyphenate CamelCase actions and views. That is, I'm hoping I don't have to actually rename my views or add decorators to every ActionResult in the site.
So far, I've been using routes.MapRouteLowercase, as shown here. That works pretty well for the lowercase aspect of URL structure, but not hyphens. So I recently started playing with Canonicalize (install via NuGet), but it also doesn't have anything for hyphens yet.
I was trying...
routes.Canonicalize().NoWww().Pattern("([a-z0-9])([A-Z])", "$1-$2").Lowercase().NoTrailingSlash();
My regular expression definitely works the way I want it to as far as restructuring the URL properly, but those URLs aren't identified, of course. The file is still ChangePassword.cshtml, for example, so /account/change-password isn't going to point to that.
BTW, I'm still a bit rusty with .NET MVC. I haven't used it for a couple years and not since v2.0.
This might be a tad bit messy, but if you created a custom HttpHandler and RouteHandler then that should prevent you from having to rename all of your views and actions. Your handler could strip the hyphen from the requested action, which would change "change-password" to changepassword, rendering the ChangePassword action.
The code is shortened for brevity, but the important bits are there.
public void ProcessRequest(HttpContext context)
{
string controllerId = this.requestContext.RouteData.GetRequiredString("controller");
string view = this.requestContext.RouteData.GetRequiredString("action");
view = view.Replace("-", "");
this.requestContext.RouteData.Values["action"] = view;
IController controller = null;
IControllerFactory factory = null;
try
{
factory = ControllerBuilder.Current.GetControllerFactory();
controller = factory.CreateController(this.requestContext, controllerId);
if (controller != null)
{
controller.Execute(this.requestContext);
}
}
finally
{
factory.ReleaseController(controller);
}
}
I don't know if I implemented it the best way or not, that's just more or less taken from the first sample I came across. I tested the code myself so this does render the correct action/view and should do the trick.
I've developed an open source NuGet library for this problem which implicitly converts EveryMvc/Url to every-mvc/url.
Uppercase urls are problematic because cookie paths are case-sensitive, most of the internet is actually case-sensitive while Microsoft technologies treats urls as case-insensitive. (More on my blog post)
NuGet Package: https://www.nuget.org/packages/LowercaseDashedRoute/
To install it, simply open the NuGet window in the Visual Studio by right clicking the Project and selecting NuGet Package Manager, and on the "Online" tab type "Lowercase Dashed Route", and it should pop up.
Alternatively, you can run this code in the Package Manager Console:
Install-Package LowercaseDashedRoute
After that you should open App_Start/RouteConfig.cs and comment out existing route.MapRoute(...) call and add this instead:
routes.Add(new LowercaseDashedRoute("{controller}/{action}/{id}",
new RouteValueDictionary(
new { controller = "Home", action = "Index", id = UrlParameter.Optional }),
new DashedRouteHandler()
)
);
That's it. All the urls are lowercase, dashed, and converted implicitly without you doing anything more.
Open Source Project Url: https://github.com/AtaS/lowercase-dashed-route
Have you tried working with the URL Rewrite package? I think it pretty much what you are looking for.
http://www.iis.net/download/urlrewrite
Hanselman has a great example herE:
http://www.hanselman.com/blog/ASPNETMVCAndTheNewIIS7RewriteModule.aspx
Also, why don't you download something like ReSharper or CodeRush, and use it to refactor the Action and Route names? It's REALLY easy, and very safe.
It would time well spent, and much less time overall to fix your routing/action naming conventions with an hour of refactoring than all the hours you've already spent trying to alter the routing conventions to your needs.
Just a thought.
I tried the solution in the accepted answer above: Using the Canonicalize Pattern url strategy, and then also adding a custom IRouteHandler which then returns a custom IHttpHandler. It mostly worked. Here's one caveat I found:
With the typical {controller}/{action}/{id} default route, a controller named CatalogController, and an action method inside it as follows:
ActionResult QuickSelect(string id){ /*do some things, access the 'id' parameter*/ }
I noticed that requests to "/catalog/quick-select/1234" worked perfectly, but requests to /catalog/quick-select?id=1234 were 500'ing because once the action method was called as a result of controller.Execute(), the id parameter was null inside of the action method.
I do not know exactly why this is, but the behavior was as if MVC was not looking at the query string for values during model binding. So something about the ProcessRequest implementation in the accepted answer was screwing up the normal model binding process, or at least the query string value provider.
This is a deal breaker, so I took a look at default MVC IHttpHandler (yay open source!): http://aspnetwebstack.codeplex.com/SourceControl/latest#src/System.Web.Mvc/MvcHandler.cs
I will not pretend that I grok'ed it in its entirety, but clearly, it's doing ALOT more in its implementation of ProcessRequest than what is going on in the accepted answer.
So, if all we really need to do is strip dashes from our incoming route data so that MVC can find our controllers/actions, why do we need to implement a whole stinking IHttpHandler? We don't! Simply rip out the dashes in the GetHttpHandler method of DashedRouteHandler and pass the requestContext along to the out of the box MvcHandler so it can do its 252 lines of magic, and your route handler doesn't have to return a second rate IHttpHandler.
tl:dr; - Here's what I did:
public class DashedRouteHandler : IRouteHandler
{
public IHttpHandler GetHttpHandler(RequestContext requestContext)
{
requestContext.RouteData.Values["action"] = requestContext.RouteData.GetRequiredString("action").Replace("-", "");
requestContext.RouteData.Values["controller"] = requestContext.RouteData.GetRequiredString("controller").Replace("-", "");
return new MvcHandler(requestContext);
}
}
Is there any way to do something like that.
I have next wiki text:
{{template_open_tag}}
{{template_some_data}}
{{template_close_tag}}
And there are templates:
{{template_open_tag}}
<my-tag>
{{template_some_data}}
bla-bla-bla...
{{template_close_tag}}
</my-tag>
But tag '<bold>' processed already when first template transluded and wiki render this page like:
bla-bla-bla...
</my-tag>
But I want to see:
**bla-bla-bla...**
In my extension:
$wgHooks['ParserFirstCallInit'][] = 'myTagInit';
function myTagInit( &$parser ) {
$parser->setHook( 'my-tag', 'myTagRender' );
}
function myTagRender( $input, $args, $parser, $frame) {
return "**".$input."**";
}
Thank you.
P.S.
And don't ask me why I need this strange markup and don't want to use something like this:
{{template_tag|{{template_some_data}}}}
And {{template_open_tag}} like:
<my-tag>{{{1}}}</my-tag>
To warn you -- this sort of structure will likely be phased out entirely in future versions of MediaWiki, due to its inconsistent behavior and the difficulties it causes with structures like tags and sections.
The correct and future-proof way to do it is indeed to contain both your start and end in one template and pass the middle in as a parameter, eg {{template_tag|{{template_some_data}}}}
Set $wgUseTidy to true to make MediaWiki remove unclosed tags only after all the templates have been evaluated. Alternatively, you can use wikimarkup - as Adrian said - which does not suffer from this limitation.
Update: AFAIK XML-style extension tags are evaluated before way template including happens, so piecing them together from multiple templates is not possible. (Event <ext>{{{1}}}</ext> does not work pre-1.16, though you can make it work in 1.16 with recursiveTagParse.)
instead of using <bold> use ''' in both your {{template_open_tag}} and {{template_close_tag}} and it should render as bla-bla-bla...
Also, you can't do:
{{template_open_tag}}
{{template_some_data}}
{{template_close_tag}}
You have to do
{{template_open_tag}}{{template_some_data}}{{template_close_tag}}