I want to include multiple controls in the items aggregation of the VBox control.
var title = new sap.m.Title({text: "Name"});
var nameInput = new sap.m.Input();
var nameText = new sap.m.Text();
var layout = new sap.m.VBox({
items: {
path: "/",
factory: function(sId, oContext) {
var type = oContext.getProperty("type");
if (type) {
return [title, nameInput];
} else {
return [title, nameText];
}
}
}
});
I want to add title and nameInput in the VBox when there is something in the type attribute and title and nameText when the type is empty or undefined. But it is returning an error:
Uncaught TypeError: o.setBindingContext is not a function
I am not sure why is this happening. It works when we return only single control in the factory function, but not the array. Does anyone has any clue how to return multiple controls in the aggregation binding using factory?
Factory function is supposed to return just one control instance, not an array. When I need multiple controls in one VBox item then I'd probably use a separate xml Fragment (e.g. another VBox or HBox) which in turn has many appropriate controls within.
Related
I want to use the following (creating a gallery card with information being provided through array for initial and a form for adding additional) I've been able to get the following function to work on information being added through the form but have not been able to get the function to work on the array I have.
function galleryAddItems(image, title){
const galleryElement = galleryTemplate.cloneNode(true);
galleryElement.querySelector(".gallery__image").src = image;
galleryElement.querySelector(".gallery__text").textContent = title;
galleryContainer.prepend(galleryElement);
}
on the array I have
const initialCards = [
{
name: "The End Place",
link: "images/cliffside__Katie-Rodriguez.jpg"
},
{
name: "Turn That Leaf Over",
link: "images/leaf__chuttersnap.jpg"
},
...
];
Currently have a second function set as
initialCards.forEach(function(thingy){
const galleryElement = galleryTemplate.cloneNode(true);
galleryElement.querySelector(".gallery__image").src = thingy.link;
galleryElement.querySelector(".gallery__text").textContent = thingy.name;
galleryContainer.append(galleryElement);
});
For this specific instance and want to avoid duplicating the code to make this work.
I've previously had galleryAddItems include .value in the function as it's needed in a different place but added that when it's being called with the hopes of it working here.
I've tried
initialCards.forEach(galleryAddItems(link, name))
and tried things like initialCards.link/.name
initialCardsLink/initialCardsName
If I don't put in parameters I'm not getting the image URL working and index is placed where I'm looking to have the name/title.
An easy way without changing your galleryAddItems() function would be:
initialCards.forEach(thingy => galleryAddItems(thingy.link, thingy.name));
Personally, I would probably think about changing the first function to something like:
function galleryAddItems(image) {
const galleryElement = galleryTemplate.cloneNode(true);
galleryElement.querySelector(".gallery__image").src = image.link;
galleryElement.querySelector(".gallery__text").textContent = image.name;
galleryContainer.prepend(galleryElement);
}
so that you could simply do:
initialCards.forEach(galleryAddItems);
You need to pass a function to the forEach function, currently, you're passing the return value of galleryAddItems since you're calling it.
I would suggest refactoring your code so that galleryAddItems takes a card as a parameter and then call it for each card using forEach.
function galleryAddItems(card){
const galleryElement = galleryTemplate.cloneNode(true);
galleryElement.querySelector(".gallery__image").src = card.link;
galleryElement.querySelector(".gallery__text").textContent = card.name;
galleryContainer.prepend(galleryElement);
}
// Call galleryAddItems for each card
initialCards.forEach(galleryAddItems)
When trying to put following Script into a CEWP on a Listview:
; (function ()
{
var fieldJsLinkOverride = {};
fieldJsLinkOverride.Templates = {};
fieldJsLinkOverride.Templates.Fields =
{
'Title': { //Titelfeld
'View': function () {
return ''+ctx.CurrentItem.Title+''
}
}
};
// Register the rendering template
SPClientTemplates.TemplateManager.RegisterTemplateOverrides(fieldJsLinkOverride);
})();
So this changes the Title field into my desired link, this works all fine, but when i try to sort the list, it returns following:
Unable to get property 'ItemID' of undefined or null
Does anyone know this problem or might find a solution for it?
You are using ctx in your code but you have not passed it to your function..
Remember Each of the functions you write for JS Link will be passed a “context” object as a parameter. From this object you can retrieve properties about the current list, current list item and other objects.
Refer below code. Here we are passing ctx to a function. Try this :
{
'Title': { //Titelfeld
'View': function (ctx) {
return ''+ctx.CurrentItem.Title+''
}
}
};
I've finally used another logic (using "let" with break), but I would be happy to have (if it's feasible) another solution:
I've built a validation service which iterate over (injected) list of objects that contains regex expressions and relevant message (and input element) for each expression. I'm using every() method to iterate over the regex expressions. The service knows to return true or false when testing the regex.
The problem is that except for getting true\false I would like the consumer of the service to get the relevant message and the input element. So, in the service class I have 2 properties (lets call them "message" and "element") and I thought to set them accordingly. But, when I'm in the context of the every - the "this" refer to the context and not to the class. I thought of sending those 2 properties as parameters to the every method. Is that the best practice?
See relevant code:
export class userValidation
{
constructor() {
this.validationMessage = '';
this.validationElement = '';
//}
validateByExpression(elementValidator, valueToValidate, functionToExec) {
var validationMessage = this.validationMessage;//Trying to get reference - no go
if (elementValidator.regex.test(valueToValidate) == false)
{
//This is the part where I need to store\return the relevant message
validationMessage = elementValidator.message; // fails
return false;
}
else
{
return true;
}
}
validate(validationElement, elementName, valueToValidate)
{
var regexExpList = new Array(validationElement);
var getValidationMessage = this.getValidationMessage;
var validateByExpression = this.validateByExpression;
var validationMessage = this.validationMessage;
return regexExpList.every(function(regexExp) { return
getValidationMessage(validateByExpression, regexExp[elementName],
valueToValidate, validationMessage) });
}
}
I am trying to structurise JS code using Revealing Prototype Pattern.
My basic usecase is: Create different types of entities like Person, Technology. Each entity has its own tags. In order to get these tags i make an ajax call which returns an object of tags. I want to access this object in my implementation. But i am not sure how to do it in right way.
My attempt is as follows:
var Entity= function (url) {
this.url = url; /*variable that can be shared by all instances*/
var entityTags;
};
Entity.prototype = function () {
var create = function (type, values) {
//code for creating
}
var update = function (type, values) {}
var tags = function () {
AjaxCall(' ', this.url, {data:data}, 'callbackAfterGetTags', '');
callbackAfterGetTags=function(responseFromAjax)
{
entityTags=responseFromAjax.tagsReturned; //how to access this entityTags in my implementation
}
};
return {
createEntity: create,
getTagsEntity: tags
};
My Implementation
var myEntity = new Entity(url);
myEntity.getTagsEntity();
Ajax call returns object successfully but i am not sure how to access the object inside tags functions in a right way. Any suggestions? This is my first trial to use OO style in JS. Let me also know if i am right track or not.
BRIEF:
I write my custom backbone editor, but Backbone can't initialize it because can't find schema for it. Backbone looks for schema in Form.editors array at backbone-forms.js? How can I register schema of my custom editor?
DETAILED:
I use Backbone Forms which are initialized in the next way:
backbone-forms.js
var Form = Backbone.View.extend({
initialize: function(options) {
//.....
//Check which fields will be included (defaults to all)
var selectedFields = this.selectedFields = options.fields || _.keys(schema);
_.each(selectedFields, function(key) {
var fieldSchema = schema[key];
fields[key] = this.createField(key, fieldSchema); // <==== Here troubles begins
}, this);
},
//....
}, {
//....
editors: {} // <===== QUESTION: where I should put my custom editor in this array???
});
Problem: When Backbone creating new Form it calls createSchema method which looks like:
createSchema: function(schema) {
//........
//PROBLEM: Form.editors[schema.type] is undefined
schema.type = (_.isString(schema.type)) ? Form.editors[schema.type] : schema.type;
return schema;
}
and Form.editors[schema.type] is undefined. That means I can't create/render my custom editor!
Question: Where/How I can register my custom editor in Form.editors array?
You can reference the custom editor directly from within the schema, i.e. reference the function itself rather than a string:
var CustomEditor = Backbone.Form.editors.Base.extend({});
var form = new Backbone.Form({
schema: {
customField: { type: CustomEditor }
}
});
Or, like you found, you can also add the editor to Backbone.Form.editors so you can use the string as a shortcut.