I've been struggling to get the bindings correct for one to many relationship using Sproutcore 2.0.
My templates look like this:
<script type="text/x-handlebars">
{{#collection contentBinding="HTH.projectsController.content"}}
<h3>{{content.title}}</h3>
{{#collection contentBinding="content.tasks"}}
<span>{{content.title}}</span>
{{/collection}}
{{/collection}}
</script>
While the actual code looks like:
HTH.Project = SC.Record.extend({
title: SC.Record.attr(String),
tasks: SC.Record.toMany('HTH.Task',{
isMaster: YES,
inverse: 'project'
})
});
HTH.Task = SC.Record.extend({
title: SC.Record.attr(String),
project: SC.Record.toOne('HTH.Project', {
isMaster: NO
})
});
HTH.Project.FIXTURES = [ { guid: 1, title: 'Send man to moon', tasks: [1,2]},
{ guid: 2, title: 'Master handstand', tasks: [3]}];
HTH.Task.FIXTURES = [ { guid: 1, title: 'Find rocket', project: 1},
{ guid: 2, title: 'Find fuel', project: 1},
{ guid: 3, title: 'Stand on hands', project: 2}];
HTH.store = SC.Store.create().from(SC.Record.fixtures);
// Controllers
HTH.projectsController = SC.ArrayProxy.create({
content: HTH.store.find(HTH.Project)
});
Now I can update tasks, and these will update the UI. For example:
HTH.store.find(HTH.Project).get('firstObject').set('title','Updated the title!');
However, if I create a new project and dynamically add a task to that the UI will add the new project, but never add any offers:
var project = HTH.store.createRecord(HTH.Project, {title: "New" });
var task = HTH.store.createRecord(HTH.Task, {title: "New task" });
project.get('tasks').pushObject(task);
I'm certain this is down to a binding not working as expected, or a property that needs to be observed. Can anyone help?
NOTE: This question was asked before SproutCore 2.0 became Ember.js. It also references an unofficial port of the SproutCore 1.x data store, which has since been superseded by the officially supported ember-data library.
In order for a record to be useable it needs to be assigned an ID.
This means that:
var project = HTH.store.createRecord(HTH.Project, {title: "New" });
var task = HTH.store.createRecord(HTH.Task, {title: "New task" });
project.get('tasks').pushObject(task);
Becomes:
var project = HTH.store.createRecord(HTH.Project, {title: "New" }, 123);
var task = HTH.store.createRecord(HTH.Task, {title: "New task" }, 321);
project.get('tasks').pushObject(task);
The changes will then be reflected in the UI
Related
I'm writing a test to register users on my site. Using #playwright/test, I have defined several different projects in playwright.config.ts:
{
name: 'iPhone 12 Pro',
use: devices['iPhone 12 Pro'],
},
{
name: 'iPhone 12 Pro Max',
use: devices['iPhone 12 Pro Max'],
},
{
name: 'iPhone 5/SE',
use: devices['iPhone SE'],
},
My test looks like this:
test('Register a user', async ({ page }) => {
// Go to baseUrl/webapp/
await page.goto(`${baseUrl}webapp/`);
// Click the register tab.
await page.click('ion-segment-button[role="tab"]:has-text("Register")');
await page.click('input[name="mail"]');
// #TODO: How do I get the project name here?
await page.fill('input[name="mail"]', `test#example.com`);
// Press Tab
await page.press('input[name="mail"]', 'Tab');
await page.fill('input[name="pass"]', 'password');
However, when I run this test, it only works for the first worker because you can only register an email address once.
So what I would like to do is to get access to the project name (for example, iPhone 12 Pro) in my test so that I can convert that to an email address so that each time the test is run, it will register a user based on the project name.
How can I get the project name within a playwright test?
I read the Playwright documentation about the workerInfo object but I can't figure out how to apply it within the test.
You have access to the workerInfo like that as a second parameter, which you can use in that case to make your email unique per worker:
test('Register a user', async ({ page }, workerInfo) => {
// Go to baseUrl/webapp/
await page.goto(`${baseUrl}webapp/`);
// Click the register tab.
await page.click('ion-segment-button[role="tab"]:has-text("Register")');
await page.click('input[name="mail"]');
await page.fill('input[name="mail"]', `test-user-${workerInfo.workerIndex}#example.com`);
You can also get the project name by workerInfo.project.name.
See here for more information.
Nice option is to access testInfo:
test('config projects name', async ({}, testInfo) => {
const projectsName = testInfo.project.name;
expect(projectsName).toEqual('chromium');
});
Tested for config:
projects: [
{
name: 'chromium',
use: {
...devices['Desktop Chrome'],
},
}
],
Docs: https://playwright.dev/docs/api/class-testinfo
Hint: In VSC during debugging you can quickly find how this object looks like
Hint2: Copy value of object testInfo from debugger and paste in new js file. Then find best parameter what suite you best (example below in Notepad++)
you can put custom project configuration -
define your custom type TestOptions:
//testOptions.ts
import { test as base } from '#playwright/test';
export type TestOptions = {
person: string;
pageName: string;
weight: number;
};
export const test = base.extend<TestOptions>({
// change later in the playwright.config.ts
person: ['AAA', { option: true }],
pageName: ['nothing', { option: true }],
weight: [0, { option: true }],
});
in playwright.config.ts add actual custom properties for the project:
import { TestOptions } from './runner/testOptions';
...
projects: [
{
name: 'demo1',
use: { person: 'Alice', pageName: 'open1', weight: 150 },
},
{
name: 'demo2',
use: { person: 'Alex', pageName: 'open2', weight: 180 },
},
...
access specific properties as
test('test project properties', async ({ page }, testInfo) => {
console.log(`--- calling project: ${testInfo.project.name}`)
console.log(`--- project.person: ${testInfo.project.use["person"]}`)
console.log(`--- project.pageName: ${testInfo.project.use["pageName"]}`)
console.log(`--- project.weight: ${testInfo.project.use["weight"]}`)
});
call actual test for given project demo1
npx playwright test -g "test project properties" --project=demo1
output:
--- calling project: demo1
--- project.person: Alice
--- project.pageName: open1
--- project.weight: 150
How i can edit asset name? its doesnt work. Thanks
let assetService = $injector.get(self.ctx.servicesMap.get('assetService'));
let activeID = self.ctx.data[0].datasource.entityId
let tenantId = self.ctx.dashboard.authUser.tenantId
let asset = {
additionalInfo: null,
createdTime: 1599121131415, // временно
customerId: {
entityType: "CUSTOMER",
id: self.ctx.dashboard.authUser.customerId
},
id: {
entityType: "ASSET",
id: activeID
},
label: null,
name: "kuku", // временно
tenantId: {
entityType: "TENANT",
id: tenantId
},
type: "справочник"
}
assetService.saveAsset(asset)
Thingsboard is built using Angular 10 currently See releases. You correctly injected the Angular service 'assetService'. You need to follow the Angular method of subscribing to the observable from assetService.
Calling
assetService.saveAsset(asset)
without subscribing means nothing happens. From the Angular University Blog
The multiple versions of the Angular HTTP module all have an RxJS Observable-based API. This means that the multiple calls to the HTTP module will all return an observable, that we need to subscribe to one way or the other.
So here's the code to 'subscribe' to the observable described above
assetService.saveAsset(asset).subscribe(
(response) => {
console.log(
"saveAsset call Success:",
response);
},
response => {
console.log(
"saveAsset call Error:",
response);
},
() => {
console.log(
"saveAsset observable Complete"
);
});
Let me know if there's a mistake in the code above, I didn't test it. And thanks for your question Anzor - it led me to a solution to make a custom Thingsboard widget along with the Widgets Development Guide.
I'm using select2 (v 4.0.3) with Bootstrap 3 and I have to display several hundreds of alternatives per optgroup. Now I wish to collapse/expand the optgroups on click to make it a bit more manageable. I couldn't find any info on this so I thought I'd post a question.
I found an approach to this problem but I couldn't get it to work (it seems a bit outdated issue #730). The basic problem with that approach now is that in the current version of select2 elements aren't created until they are needed. Also, the class names seem to have changed a bit, as have apparently the names of events in the move to the latest version.
So far I've managed to get the collapse/expand functionality to work for the optgroups, but issues arise when the user provides text input (check the fiddle).
$(function () {
var data = [
{
text: "Group 1",
children: [
{ id: 'A1', text: 'a1'},
{ id: 'B2', text: 'b2'},
{ id: 'C3', text: 'c3'}]
},
{
text: "Group 2",
children: [
{ id: 'A2', text: 'a2'},
{ id: 'B3', text: 'b3'},
{ id: 'C1', text: 'c1'}
]
}];
$('#mySelect')
.select2({data: data, placeholder : 'Select one' });
// Toggle group on click
$('.select2')
.on('click', function(){
$('.select2-results__option').on('click', function(){
$(this).find('.select2-results__options--nested').toggle();
});
});
});
When the text input is used select2 runs the search and the events I've registered are dropped. My plan was to capture text input and check if the input field is empty or not, based on which I can decide to recreate the optgroup listeners or show all optgroups. Any help in this direction would be appreciated.
I have a simple model in Backbone.js with few configurations:
budget.Group = Backbone.Model.extend({
url: '/groups'
})
...now when I do something like this:
budget.Group.save({ id: 1, name: 'Food' });
... it attempts to PUT it to the following URL:
/groups
.. but my (Rails) app would post/put it to:
/groups/1
Do I need to configure my model to update to the correct url? Thanks
You should be doing
var budget = new budget.Group({ id: 1, name: 'Food' });
budget.save();
Backbone will do the rest for you (and use the correct URL).
As the two answers before mentioned you must instantiate your Model :
var budget = new budget.Group({ id: 1, name: 'Food' });
budget.save();
But you have also to change the url property to urlRoot
budget.Group = Backbone.Model.extend({
urlRoot: '/groups'
})
Is it possible somehow to group results in a Select2 component when it's not using <select> tag, but <input type="hidden">, and results are provided as "data" option in configuration object?
var select2Options = {
data: {
results: myArrayOfResults
}
};
Yes, the results objects support a children attribute...
so for example:
var select2Options = {
data: {
results: [
{text: "My shiny group", children: [
{id: 1, text: "My shiny item"},
{id: 2, text: "My shiny item2"}
]}
]
}
};
For ajax data loading with group and data work for me using,
$arrFinal = array(array("name"=>"My shiny group 1",
"children"=>array(array("id"=>1,"name"=>"My shiny item 11"),array("id"=>2,"name"=>"My shiny item 12"))
),array("name"=>"My shiny group 2",
"children"=>array(array("id"=>1,"name"=>"My shiny item 21"),array("id"=>2,"name"=>"My shiny item 22"))
)
);
die(json_encode(array("result" => $arrFinal)));
if formatResult: ratioFormatResult then,
function ratioFormatResult(row) {
// Here, you will get both group ("My shiny group 1") as well as data("My shiny item11") as row .
}
To make group selectable use id field along with name in group.