How to fix the red mark that appears when using binding.scala in intellij? - scala

I am developing with scalajs and binding.scala. I'm using the IDE as an Intellij. However, when using dom macro in Intellij, the following red mark appears. this error appears when I use the attribute value of id in the input element as macro What is the solution?
This error(a.k.a. "cannot resolve symbol something") appears when you use the id attribute value of the input element as marco.
please see the link of image below.
this is my code image.
#dom
def render: xml.Elem = {
val name: _root_.com.thoughtworks.binding.Binding.Var[_root_.java.lang.String] = Var.apply("Binding.scala")
val show: _root_.com.thoughtworks.binding.Binding.Var[Boolean] = Var.apply(false)
<div>
<p>
<label for="showCheckbox">
<input type="checkbox" id="showCheckbox" onchange={e: Event => show.value = showCheckbox.value }/>
<span> Say hello to <input id="nameInput" value={name.value} oninput={_: Event => name.value = nameInput.value}/></span>
</label>
</p>
{
if (show.bind) {
<p>
Hello, {name.bind}!
</p>
} else {
<!-- Don't show hello. -->
}
}
</div>
}

I actually have the same problem. I have 2 ways dealing with it:
Ignore these exception - as they are only a problem within IntellIJ
(it compiles just fine).
Use for example JQuery like this:
import org.scalajs.jquery.jQuery
..
jQuery("#showCheckbox").value()
As soon as your id gets more dynamic - you will need something like that anyway (at least that is what I know;)) -> jQuery(s"#${elem.id}").value().

You could take advantage of the scalaJS Event passed in, maybe something like:
oninput={ev: Event => name.value = ev.target.asInstanceOf[HTMLInputElement].value}

Related

How to simulate ionBlur in tests

Maybe I'll start with what I want to achieve: I have a form with a required field. By default it should not display any error. The error should be displayed if a user touches the field. So my field looks more or less like this:
<ion-input .... (ionBlur)="updateDispayedErrors()"></ion-input>
But I don't know how to test it because:
Running fixture.debugElement.nativeElement.blur() does not triggers ionBlur handler (the same with ....dispatchEvent(new Event('blur')))
Plain angular (blur) does not work (i.e. if I change the code to (blur)="updateDisplayErrors()" then it does not work)
It seems that calling blur() method on native <input .../> element that is created in the browser would work but... the problem is that when I run the tests fixture.debugElement.nativeElement.childNodes is empty... So the native <input .../> is not created
Please let me know if you would like to see a full example to illustrate it.
If you add a selector to ion-input like:
<ion-input .... (ionBlur)="updateDisplayedErrors()" id="specialInput"></ion-input>
Then you can use fixture.debugElement.triggerEventHandler:
import { By } from '#angular/platform-browser';
...
it('should emit ionBlur', () => {
const ionDe = fixture.debugElement.query(By.css('#specialInput'));
const ionBlurResult = spyOn(component, 'updateDisplayedErrors');
ionDe.triggerEventHandler('ionBlur', {});
expect(ionBlurResult).toHaveBeenCalled();
});

Passing multiple data points to an action? VUEX

So I have a form that collects 3 data points that looks like this:
<form class="" >
<table>
<tr>
<td>Maximum Temperature</td>
<td><input class="setSettings" v-model="settings.maxTMP" type="number" max="30" min="5"></td>
</tr>
<tr>
<td>Minimum Humidity</td>
<td><input class="setSettings" v-model="settings.minHUM" type="number" max="95" min="20"></td>
</tr>
<tr>
<td>Maximum CO2</td>
<td><input class="setSettings" v-model="settings.maxCO2" type="number" min="200" max="5000" step="10"></td>
</tr>
</table>
<button type="button" v-on:click="whatSettings(settings)">Update Settings</button>
</form>
My data in the script tag is stored in the components local data, not the store, ike this:
data: function() {
return {
settings: {
maxTMP: "",
minHUM: "",
maxCO2: ""
}
}
}
There's no reason to put it through a mutation and commit it to the store as the purpose for the action is merely to send the data via post request to receiving api.
My methods for the component look like this:
methods: {
...mapActions({
setSettings: 'setSettings'
}),
whatSettings(settings){
let foo = settings.maxTMP;
let bar = settings.minHUM;
let uhm = settings.maxCO2;
console.log(foo);
console.log(bar);
console.log(uhm);
this.setSettings(foo,bar,uhm)
}
},
And that action from the store is write like this:
setSettings(foo,bar,uhm) {
console.log("Set these settings");
console.log(foo);
console.log(bar);
console.log(uhm);
},
Please forgive all the console.log()'s. I have it like this cause I was trying to test out different combinations of things to figure out where it goes wrong. Right now when I click the Update Settings button the console prints the whatSettings() correctly so I know that foo, bar, uhm are the correct value as they are passed into the setSettings() action. The problem is in the action's logs. "Set these settings" and foo are printed correctly followed by a single undefined, not two. So I'm not sure exactly what's happening with bar & uhm. When I rearrange the order it's always the first that gets printed.
Is it a problem with multiple arguments being passed to the action? Ideally I would just like it to look like this directly in the button tag for neatness but that didn't work so I tried trouble shooting like this:
v-on:click="this.setSettings(settings.maxTMP, settings.minHUM, settings.maxCO2)"
Thanks for reading and I appreciate the help!
Well, after a little more looking around I found this and it fixed my problem: Axios post request with multiple parameters in vuex action
correct button tag:
<button type="button"
v-on:click="setSettings({
foo: settings.maxTMP,
bar: settings.minHUM,
uhm: settings.maxCO2
})"
>Update Settings</button>
correct vuex store action:
setSettings({commit}, {foo, bar, uhm}) {
console.log("Set these settings");
console.log(foo);
console.log(bar);
console.log(uhm);
},
Not entirely sure why the {commit} needs to be present, but it does otherwise I just get 3 undefined results in the log. But it works now!

Row and column method missing on element.all

I have the following setup, where I want Protractor to click on a row (or the checkbox in a row, either is fine):
<li data-ng-repeat="room in chatRooms | ***filters***">
<div ng-click="toggleJoin(room.id)">
<input type="checkbox" value="{{room.id}}" ng-checked="isChecked(room.id)" />
<span>{{room.name}}</span>
</div>
</li>
And I want to do this with my Page Object:
var PageObject = function() {
this.lstChatRooms = element.all(by.repeater('room in chatRooms'));
this.clickChatRoom = function(index) {
this.lstChatRooms.row(index).column('{{room.id}}').click();
};
};
But when I try to call clickChatRoom with some index in my test, I get an error saying the object has no method 'row', and I've seen the same behavior with 'column'. I'm not calling anything on the list of chat rooms prior to this in my test, so the promise should not be resolved at that point. What am I doing wrong?
Update: The issue may be caused by this bug. Unless anyone can see that I'm doing something wrong with the API or something else.
i can't test it right now, but this should work for you:
this.lstChatRooms.then(function(rooms) {
rooms[index].findElement(by.tagName('input')).click();
});

Radio button in Lift?

I'm trying to render a radio button choice in my webapp but I have some problems.
What I have done is to try jcern solution posted in this answer:
get checkbox and radio button value in lift
This is my HTML code:
<div class="lift:Radio.render">
<input id="choice" name="choice" type="radio"/>
</div>
And this is my SCALA code:
object Radio {
def render = {
val radioChoices = List("Choice_1", "Choice_2")
var choice:Box[String] = None
"name=choice" #> SHtml.radio(radioChoices, choice, (resp) => choice = Full(resp))
}
}
But the compiler give me an error on binding:
could not find implicit value for parameter computer:net.liftweb.util.CanBind[net.liftweb.http.SHtml.ChoiceHolder[String]]
[error] "#choice" #> SHtml.radio(radioChoices, choice, (resp) => choice = Full(resp))
[error] ^
I have to bind with .toForm to pass compile like this:
"name=choice" #> SHtml.radio(radioChoices, choice, (resp) => choice = Full(resp)).toForm
The problem is that no radio buttons are displayed on my web page, nothing at all..
Am I doing something wrong? I can't see it. And why the first solution (without .toForm) give me an error at compile?
The reason is that SHtml.radio and SHtml.radioElem return a ChoiceHolder instead of a the NodeSeq that most other items in SHtml do - as you can see in the API Doc. Because of that, you need to call .toForm or render the output yourself.
Returning the ChoiceHolder allows you to customize how each item is displayed, so you can add custom text for the label, etc... If the basic toForm output didn't work for you, you could do something like:
val choices = SHtml.radio(radioChoices, choice, (resp) => choice = Full(resp))
"#choice" #> choices.items.zipWithIndex.map { case(itm, pos) =>
val rId = "myId-%s".format(pos)
<div class="radio">{
//We'll add a custom ID attribute to the radio button
itm.xhtml.asInstanceOf[Elem] % ("id", rId)
}<label for={ rId }>{
//Output the toString or use some other method to output a label
itm.toString
}</label>
</div>
}
You can find more information on customizing the radio buttons in the Lift Cookbook.
As for why your CSSSelector is not outputing anything, I am not sure. The code snippet you were trying worked for me. The screenshot below illustrates the output I see with the toForm method.

How to hide a text field in play framework

How to hide a text field in play framework? For example how to hide this field:
#inputText(userProfileForm("name"), '_label -> "Name")
This should work in all browsers:
#inputText(
userProfileForm("name"),
'_label -> "Name",
'style -> "display: none"
)
Note that this only hides the field, not the label etc.
If you want to hide the label aswell, you can't do this with the default helpers.
You can however specify the input field yourself:
<input type="hidden" name="name" value="#userProfileForm.data.get("name")" />
The name should be name of the field in your form (coincidentally name aswell in this case).
I haven't tested the value but it should work, maybe you'll need to strip the " around name.
If you do this, the hidden data will be sent, along with the other data in the form to the server.
Edit:
If the hidden value is empty, that means you didn't bind it to the form when calling the view. You can bind the name to the form like this in Java (I don't know Scala, but it's explained in the Play Scala documentation):
Map<String, String> data = new HashMap<>();
data.put("name","get the username here");
return ok(index.render(userProfileForm.bind(data));
Another option (which is cleaner in my opinion) is to simply pass the username as an argument to the view. The controller becomes:
return ok(index.render(userProfileForm, "username goes here"));
And in the view you can then simply do:
#(userProfileForm : Form[UserProfileForm])(name : String)
#helper.form(...){
<input type="hidden" name="name" value="#name" />
//...
}
The inputText helper takes a varargs of (Symbol, Any), which represent the html attributes. If you are using html5 you can just add the hidden attribute:
#inputText(userProfileForm("name"), '_label -> "Name", 'hidden -> "hidden")
normally the hidden attribute has no value, but I couldn't find any information about how to do this with the helpers. In Chrome at least it works like this as well.
edit:
btw, you can also just use html instead of the helper:
<input attribute=value hidden />
I know that this is an old question, but i had a similar issue, i wanted to hide an inputText and still, handle it using the helpers.
The best and cleanest way to do it is to write your own helper adding a custom value to tell when to hide the element itself.
I came to a solution like this
my own field constructor
#(elements: helper.FieldElements)
#if(elements.args.contains('hideIt)){
#elements.input
}else{
<div class="#if(elements.hasErrors) {error}">
<div class="input">
#elements.input
<span class="errors">#elements.errors.mkString(", ")</span>
<span class="help">#elements.infos.mkString(", ")</span>
</div>
</div>
}
that i used in the view file like this:
#inputText(form("fieldName"),
'hidden -> "true",
'hideIt -> true
)
now you are done :)
While it worked, I didn't like the hashmap version provided by #Aerus, preferring to use the statically typed forms when possible, so I came up with an alternative.
final UserProfileForm initial = new UserProfileForm("get the username here");
return ok(index.render(Form.form(UserProfileForm.class).fill(initial));
Then, in the profile, you can do as follows:
<input type="hidden" name="name" value="#userProfileForm("name").value" />