This has been driving me nuts - hoping someone can help me.
I have a multifield component called 'books' with a single textfield: 'title'.
Everything seems to be working; the dialog box contains the multifield then I add two title fields then enter 'title1' and 'title2'.
then in the HTML itself I go:
<div data-sly-repeat="${properties.books}">
<p>${item}</p>
<p>${itemList.index</p>
<p>${item.title}</p>
</div>
What I don't get is, ${item} correctly gives me:
{"title": "title1"} {"title": "title2"}
and ${itemList.index} correctly gives me: 0 1
but ${item.title} keeps coming up blank. I also tried ${item["title"]} and that comes up blank too.
What am I doing wrong here? In my desperation I contemplated using
<div data-title="${item}"></div>
and then using JS to process the JSON object but I don't really want to do that.
Someone help, please!
It looks like your books property is either a JSON array string or a multivalued property with each value being a JSON object string;
The easiest way to parse the property is via a JS model like the following:
You could simplify this script to match your specific case, I made it general to multi-value and non-multi-value string properties.
/path/to/your-component/model.js:
"use strict";
use(function () {
// parse a JSON string property, including multivalued, returned as array
function parseJson(prop){
if(!prop) return [];
var result =[];
if(prop.constructor === Array){
prop.forEach(function(item){
result.push(JSON.parse(item));
});
}
else {
var parsed = JSON.parse(prop);
if(parsed.constructor === Array){
result = parsed;
}
else result = [parsed];
}
return result;
}
var $books = properties.get("books", java.lang.reflect.Array.newInstance(java.lang.String, 1));
var books = parseJson($books);
return {
books: books
}
});
/path/to/your-component/your-component.html:
<sly data-sly-use.model="model.js"/>
<div data-sly-repeat="${model.books}">
<p>${item}</p>
<p>${itemList.index</p>
<p>${item.title}</p>
</div>
Related
HTML
<ion-input [(ngModel)]="login.username" ngControl="username1" type="number" #username1="ngForm" id="userName" required>
</ion-input>
PROTRACTOR TEST CODE
let usern: ElementFinder = element.all(by.css('.text-input')).get(0);
usern.sendKeys('error');
expect(usern.getAttribute("value")).toEqual("error");
browser.sleep(500);
usern.clear();
browser.sleep(1000);
usern.sendKeys('12345');
The element is found but no text is entered into the field. If I change the element to type="text" the protractor command works.And the page view is 'e' and can't be clear.
Secondly if I send string like this: "we2124will", the actually send data is '2124' and the result from getAttribute("value") is 2124.
Thirdly even if I changed the sendKeys to number, the result is not full number string. For example:
Failures:
1) Login page should input username and password
Message:
Expected '125' to equal '12345'.
Stack:
Error: Failed expectation
There are some number missing.
Since you're using an <ion-input>, the actual HTML <input> tag will be nested within, and it won't have an id attribute. The effect is that the wrong element can get selected.
Try something like below to grab the nested input tag:
let username = element(by.id('userName')).all(by.tagName('input')).first();
username.sendKeys('fakeUser');
That worked for me.
As a workaround, you can introduce a reusable function that would perform a slow type by adding delays between send every key.
First of all, add a custom sleep() browser action, put this to onPrepare():
protractor.ActionSequence.prototype.sleep = function (delay) {
var driver = this.driver_;
this.schedule_("sleep", function () { driver.sleep(delay); });
return this;
};
Then, create a reusable function:
function slowSendKeys(elm, text) {
var actions = browser.actions();
for (var i = 0, len = text.length; i < len; i++) {
actions = actions.sendKeys(str[i]).sleep(300);
}
return actions.perform();
}
Usage:
var elm = $("ion-input#userName");
slowSendKeys(elm, "12345");
What version of protractor are you using?
Not sure this is the issue but try grabbing the element by ng-model
var elem = element(by.model('login.username'));
elem.sendKeys('error');
expect(elem.getAttribute("value")).toEqual("error");
elem.clear();
elem.sendKeys('12345');
expect(elem.getAttribute("value")).toEqual("12345");
I have a meteor helper that uses a reactive variable in a find to get a unique document using an id. My item button template looks like this:
<template name = "itemButton" >
<div class = "itemButton" name = {{_id}}>
{{{title}}}
</div>
</template>
using a reactive variable:
Template.landing.onCreated(function _OnCreated() {
this.f = new ReactiveVar();
this.f.set(false);
const handle = Meteor.subscribe("Feed");
});
now I have a method in a template several itemButton.
Template.landing.events({
'click .itemButton' : function(event, template){
alert(event.target.name);
template.f.set(event.target.name);
}
});
and I would like to use that name in a helper that would use this value as the _id.
Template.landing.helpers({
"GetFocus": function(){
alert(Template.instance().f.get()); // alerts undefined...
return(items.find({'_id':Template.instance().f.get()}));
}
});
So where I expect GetFocus to give me the document that generated the button I don't seem to be so lucky. Let me know if I can provide any additional clarification, and as always your input is appreciated.
Where I have template.f.set(event.target.name); I needed template.f.set(event.currentTarget.getAttribute('data-id')); where the html uses data-id instead of name.
In jQuery, there is a function to serialize a form element so for example I can submit it as an ajax request.
Let's say we have a form such as this:
<form id="form">
<select name="single">
<option>Single</option>
<option selected="selected">Single2</option>
</select>
<input type="checkbox" name="check" value="check1" id="ch1">
<input name="otherName" value="textValue" type="text">
</form>
If I do this with the help of jquery
var str = $( "form" ).serialize();
console.log(str);
the result would be
single=Single2&check=check1&otherName=textValue
Is there such functionality in dart's FormElement or I have to code it myself? Thanks.
I came up with my own simple solution that might not work in all cases (but for me it is workikng). The procedure is this:
First we need to extract all input or select element names and values from the form into Dart's Map, so the element name will be the key and value the value (e.g. {'single': 'Single2'}).
Then we will loop through this Map and manually create the resulting string.
The code might look something like this:
FormElement form = querySelector('#my-form'); // To select the form
Map data = {};
// Form elements to extract {name: value} from
final formElementSelectors = "select, input";
form.querySelectorAll(formElementSelectors).forEach((SelectElement el) {
data[el.name] = el.value;
});
var parameters = "";
for (var key in data.keys) {
if (parameters.isNotEmpty) {
parameters += "&";
}
parameters += '$key=${data[key]}';
}
Parameters should now contain all the {name: value} pairs from the specified form.
I haven't seen anything like that yet.
In this example Seth Ladd uses Polymers template to assign the form field values to a class which get's serialized.
Below is the prototype of what I am trying to do.
var entry_set = $;
// start to loop data
for([])
{
// create HTML element to represent that data
$('<div></div>')
.data([])
.addClass([])
.on([])
.insertAfter(entry_set);
}
// modify DOM only once all the entries are consolidated to a single jQuery object
entry_set.appendTo('.entries');
The comments say it all. In short - the idea is to modify document DOM only once when inserting data. I would usually go HTML string approach (simply concatenating the same structure using a string), but I am interested whether anything similar to this might work as well.
You could create an empty DOM element and .append() to that
var entry_set = $("<div>"); //empty dom element
// start to loop data
var i = 4;
while(i--) {
// create HTML element to represent that data
var item = $('<div>', {
text: "test " + i
});
entry_set.append(item);
}
// modify DOM only once all the entries are consolidated to a single jQuery object
$("body").append(entry_set.children());
working demo at: http://jsfiddle.net/F2J6g/1/
EDIT
You can also start with an empty collection and use .add()
var entry_set = $(); //empty collection
// start to loop data
var i = 4;
while(i--) {
// create HTML element to represent that data
var item = $('<div>', {
text: "test " + i
});
entry_set = entry_set.add(item);
}
// modify DOM only once all the entries are consolidated to a single jQuery object
$("body").append(entry_set);
http://jsfiddle.net/F2J6g/2/
#Guy, I don't think you will get the desired HTML output. try using "wrap".
Sample Syntax:
$('.OuterDiv').wrap('<div class="abc" />');
Unfortunately, because those objects aren't actually attached to any heirarchy, calling insertAfter doesn't actually mean anything. What you'll need to do is put them inside a containing div, maybe something like this:
var entry_set = $('<div>');
// start to loop data
for([])
{
// create HTML element to represent that data
$('<div></div>')
.data([])
.addClass([])
.on([])
.appendTo(entry_set);
}
// modify DOM only once all the entries are consolidated to a single jQuery object
entry_set.appendTo('.entries');
I haven't tested that, but I think it should work.
I'm trying to display an error message if the select button in my form is not changed. It works fine for the rest but not the select, please help! and I know that the image wont work like that, I cant post images as a new member.
Html is:
<div id='first_name_error' class='error'><image code here></div>
<div><input type='text' name='first_name' id='first_name' placeholder="YOUR FIRST NAME*"></div>
Number of Guests:*<div id='guests_error' class='error'><img src='img/booking/error.png'></div>
<div><select name='guests' id='guests' style="margin:0px;" SIZE="1"><OPTION SELECTED value="guests">Guests<OPTION>2<OPTION>3<OPTION>4</SELECT></div>
Code Is
var error = false;
var first_name = $('#first_name').val();
var second_name = $('#second_name').val();
var email = $('#email').val();
var number = $('#number').val();
var guests = $('#guests').val();
var message = $('#message').val();
if(first_name.length == 0){var error = true;$('#first_name_error').fadeIn(500);}else{$('#first_name_error').fadeOut(500);}
if(guests.value == Guests){var error = true;$('#guests_error').fadeIn(500);}else{$('#guests_error').fadeOut(500);}
Notice that your "guests" variable is already set to the value of the select element (using jQuery val()). There is no need to attempt to access the "value" property of the "guests" variable.
Second, the comparison you are making is to the identifier Guests, not to the string "Guests". You'll want to put quotes around that to make it a string literal.
You can see an example of this here: http://jsfiddle.net/tbuCJ/