How to access the message from a MessageListItem / Message bubble? - plugins

I need to access each message in a twillo agents chat to check if any of them are a link, if so I will render a component.
I tried using
flex.MessageListItem.Bubble.Content.message
but I think I am using it wrong.

To edit a specific component that has some link in the message content you'll need to use Content.add (if you want to add a new component to the message bubble) or Content.replace (to replace the component for another that you'll create). In Both methods, replace and add, you can pass an if property that will receive that logic to add/replace or just render the default component.
Follow an example where I replace a default component with another based on a condition:
flex.TaskInfoPanel.Content.replace(<CallbackComponent key="callback-info-component" manager={manager} />, {
sortOrder: -1,
if: (props) => props.task.attributes.taskType === 'callback',
});
To see what coming in condition props you can simply print it using a console.log, so the if condition returns true, it'll replace or add your component, if returns false, it'll doesn't anything.
Follow some docs that can help you:
Flex 1.0 components
Flex 2.0 components
I hope that it can help you.

Related

Updating Angular 6 Form value in case corresponding dom native element value is modified by external library

I am experimenting cobrowsing with Angular 6 Forms.In co-browsing an opensource library togetherJS updates the DOM value of corresponding element for remote party.I have updated togetherJS related code in index.html(two line one in head and another in body) I have observed using ControlValueAccessor Form type DOM value of corresponding element is getting updated but FormControl value is not getting updated in view.
My question is how changes done by an external library on DOM elements can be reflected into angular 6 form control's element value in view.
One can get the code from below link:
https://github.com/srigaurav1986/Angular-Forms.git
How to reproduce:
1.Download code from above link.
2.Install dependencies using "npm install"
3.Run "ng serve -o"
4.open in browser "http://localhost:4200/controlvalueaccessor"
5.Click on "Start TogetherJs"
6.Copy the popped link in another browser window.
7.Update the "Name" field
We can see DOM field value is also getting updated on remote side but after pressing "Submit" button we can see FormControl value remains unaltered on remote side but changed on other side.
I tried using manually detecting changes using application.tick,markforcheck() and detectchanges() apis but no luck.Is there a way, where we can listen to some event on DOM element change and subscribe to it and also update the Formcontrol parameter values in such case.
The answer to this question lies in angular(6) property that it works on shadow DOM and only listen to the changes happening within angular zone , when the third party library like TogetherJS updates DOM corresponding changes doesn't effect angular components as they are not subscribe to actual DOM native element.
In order to resolve this issue we did following :
Register one call back in Form class constructer to capture DOM “change” events triggered from Co-Browsing library i.e. happening outside angular zone as mentioned below:
Code Snippet
constructor(private formBuilder: FormBuilder,private elementRef: ElementRef,private _renderer: Renderer,private cdr:ChangeDetectorRef,private app:ApplicationRef,private zone:NgZone) {
zone.runOutsideAngular(() =>{
window.document.addEventListener('change', this.change.bind(this));
})
}
Define the eventHandler to perform below actions :
Run in Angular context using this.zone.run()
Use ElementRef to get the component’s template selector.
Run queryselector on input elements and compare with event’s outerHTML to check which element has changed in component.
Set the Formcontrol’s value for matching element.
PS: Here customerForm is ControlValueAccesor FormGroup type of instance. In your case it can be your form. We can generalize form( In case reactive) key traversal as mentioned in another SO post
Angular 2: Iterate over reactive form controls
Code Snippet:
change(event){
event.preventDefault();
console.log("DOM value changed" ,event);
console.log("component value", this.elementRef.nativeElement);
this.zone.run(() => { console.log('Do change detection here');
//this.cdr.detectChanges();
if(this.elementRef.nativeElement.querySelectorAll('input')[0].outerHTML === event.target.outerHTML)
{
console.log('Inside value updation');
//this.customerForm.controls.name.value=event.target.value;
this.customerForm.controls['name'].setValue(event.target.value);
}
});
setTimeout(() =>{
this.cdr.markForCheck();
})
}
This will set the respective values of elements(obviously via traversing loop) changed in component and validation should not fail as it’s happening in current context.
The core idea of above details is how to capture change events happening outside angular zone and updating angular application accordingly.
PS : I shall update the full code in github for other's perusal.

Umbraco 7 - Extending RTE settings

My goal is to extend umbraco's Rich Text Editor data type to include a "char limit" field. Then, when using the data type in document type editor, there would be a field for a char limit to be set (rather than using a regex validation for that).
I have googled but the only thing I found until now was how to extend the RTE to add more buttons.
Is this achievable?
Thanks ;)
You can overwrite RTE's 'onKeyDown' event and handle the limit in the function's body. The url you provided in example shows how to create a field.
tinyMCE.activeEditor.on("keydown", function(e){
console.log(e.keyCode); //Your logic goes here
});
The next steps depend on how you are going to create your char limit. The easier solution is to set up a validation onSave event, also you can parse keydown's event object and return false, if the limit is exceeded

Single select Tag in Touch UI

OOTB Tag has multi select functionality, Is it possible to create single select Tag in Touch UI? If yes, can you point me which js file I need to modify?
The cq:tags property is rendered by CUI.TagList widget that can be found within /etc/clientlibs/granite/coralui2/js/coral.js script.
Reading it you can learn that the widget raises itemadded event which might be helpful for you to handle the singular tag handling. An example function that can catch the event might be placed in any clientlibs that will be attached to the admin interface such as cq.authoring.dialog clientlib.
$('*[data-fieldname="./cq:tags"]').on('itemadded', function(ev, value) {
var el = $(ev.target),
div = el.siblings('div'),
input = div.find('input'),
button = div.find('button');
input.prop('disabled', true);
button.remove();
}
To have the fully functional flow you need to handle the itemremoved event as well and make the input field enabled again as well as add the button back to the widget.

GTM Reduce number of tags

GTM up and running, main UA tag in place along with a ClickListener tag.
To reduce the number of macros, i use dataLayer variable Macros for event category, action, label, value & interaction, so they can be used for many rules and tags.
So i want to collect data from one link/button (Add to Fav), i add a rule to listen for the click using {{event}} equals gtm.click and {{Event Label}} equals Add_to_Fav (the label i push to the DL via onclick.
All good so far, but i need to create another UA tag (Track Type - event) that fires on the rule made previously. And this is my question, using this method seems to create many tags. If i have another 20 links that i want to collect data from, do i need to keep creating tags like this. Surely, this will affect page load speed with many tags firing on all pages.
Hope thats all clear.
If you need to retrieve the link text to use it as an event label you do not need many many event tracking tags, that would be horribly verbose. Instead you can use a custom javascript macro - the cool thing about them being that you can use existing macros inside your custom function.
If you create a click listener or link click listener this will create a few macros - one of them is {{element}}, which is the DOM element that received a click.
Now you create a macro of the type "custom java script", which must contain an anonymous function with a return value.
The barebones version of a function that retrieves the text of a clicked link would be
function() {
var el = {{element}};
return el.innerText;
}
(actually you do not need the variable assigment, you could use {{element}}.innerText directly).
You name the macro e.g. Linktext and use the macro {{Linktext}} in your single event tracking tag where it will dynamically be set to the value of the text of the clicked link (although you might want to check cross browser support for innerText, or maybe use innerHTML instead which serves in you use case probably the same purpose).

How to remove a validator from a Select?

I have a form where I need to add/remove validators dynamically. Based on a dropdown selection, other form fields may have different validation rules.
For other kinds of inputs, I've used replace(methodThatCreatesTheInput()) to get rid of a previously added validator. (Not knowing of a better way. Specifically, there doesn't seem to be any way to directly remove a validator from a component...)
With Select, from wicket-extensions, this approach fails with something like:
WicketMessage: submitted http post value [[Ljava.lang.String;#5b4bf56d]
for SelectOption component [8:myForm:targetInput] contains an
illegal relative path element [targetConsortiums:1:option] which does not
point to an SelectOption component. Due to this the Select component cannot
resolve the selected SelectOption component pointed to by the illegal value.
A possible reason is that component hierarchy changed between rendering and
form submission.
The method that creates the Select:
private FormComponent<?> targetSelection() {
Map<Class<? extends Target>, List<Target>> targets = targetService.getAllAsMap();
SelectOptions<Target> propertyOptions = new SelectOptions<Target>("targetConsortiums",
targets.get(Consortium.class), new TargetRenderer());
SelectOptions<Target> consortiumOptions = new SelectOptions<Target>("targetProperties",
targets.get(Property.class), new TargetRenderer());
Select select = new Select(ID_TARGET, new PropertyModel<Target>(model, "target"));
select.add(propertyOptions);
select.add(consortiumOptions);
select.setRequired(true);
select.setMarkupId(ID_TARGET);
return select;
}
(Why use a Select instead of normal DropDownChoice? We want the two types of choices to be clearly separated, as documented in this question.)
Any ideas how to solve this? What I'm trying to achieve is, of course, very simple. Unfortunately Wicket disagrees, or I'm using it wrong.
Wicket 1.4.
I don't know how to do this on Wicket 1.4, but on Wicket 1.5 there is a remove method for validators on FormComponent (see javadoc)