I'm working with Material Components for Angular 5, and have a form control that is an autocomplete for that is powered by a service call. Unfortunately, until the service call is complete, the autocomplete does not show, and due to some network latency issues we are experiencing at the moment, most users are finished typing before the service call completes. I'd like to show some kind of visual indicator that the autocomplete is loading, but cannot figure out how to do it.
The cheap solution we tried was to populate the autocomplete menu with the work "Loading" however this would require tweaking our filtering so that it didn't immediately get squashed when someone started typing a value that didn't start with l.
This is the basics of our HTML for one of the fields:
<mat-form-field [hideRequiredMarker]="true">
<input matInput [(ngModel)]="size" type="text"
placeholder="{{'OPTIONS.SIZE' | translate}}"
[matAutocomplete]="autoSize"
readonly="{{!model}}"
(keyup)="filterSizes()"
matTooltip="{{ 'OPTIONS.MODEL_REQUIRED' | translate }}"
[matTooltipDisabled]="model != ''" />
<mat-autocomplete #autoSize="matAutocomplete">
<mat-option *ngFor="let completeSize of filteredSizeNames" [value]="completeSize">
{{completeSize}}
</mat-option>
</mat-autocomplete>
</mat-form-field>
The service call populates the filteredSizeNames variable when it completes. I looked through the material component pages without much luck figured out a soluation.
Use an indeterminate progress indicator bound to a "loading" variable that gets "turned on" when the service call starts and turned off when the service returns. One way is to place a progress circle in the form field as a prefix or suffix. You could also use a progress bar that is styled to position it directly over the form-field's underline (this is a lot of work to get the position just right, but it can be done and looks quite slick).
An easier solution would be to just use the form field label text updated the same way.
Related
Recenty, I noticed that the checkboxes that I wrote a click event worked incorrectly from time to time. Not everytime but sometimes their #click event works in reverse. Here is what I am trying to tell;
<label class="form-switch">
<input type="checkbox" #click="showElement = !showElement"/>
</label>
I have a simple form switch and there are some css on it which I didn't put here, it looks like a toggle switch. It toggles a data which is showElement. The default state of the data is false and when you click on the toggle it becomes true and false respectively.
<div v-show="showElement>
some content here
</div>
When the showElement is true I want to display the above div, and when it becomes false, I want it to be hidden. There is no problem with that. But here is my question;
If my observation is corret, usually when the project is started for the first time, in other words, when I type npm run serve and start the project, I immadiately go and check if it is working fine or not so I click on the checkbox very quickly over and over andsometimes the click event breaks down and starts working backwards. I mean, when the switch is off, the content is visible, when it is false, the div is showing, but it should be reversed. This happens sometimes when I browse the other pages of the project and return to this component. Is this a bug? Or am I doing something wrong? In the first version of the code it was like below;
<label class="form-switch" #click="showElement = !showElement>
<input type="checkbox"/>
</label>
I accidentally typed the click event to the label element instead of input. I thought that might be the problem. I am still thinking that is the problem but the bug that I explained above still happens sometimes. Do you know why? Can anyone explain?
Usually i find that with checkboxes in VueJS #Click is not the way to go. Try to use #Change event instead. This should make it more consistent.
The reason behind this is that the click event triggers before the value has been updated. Therefore creating the risk of it overwriting the old value instead of the newly updated one
EDIT:
I actually think in this case you might even be able to get around this by simply adding a v-model to the checkbox like so:
v-model="showElement" instead of having either #click or #change.
Verison 1:
<label class="form-switch">
<input type="checkbox" #change="showElement = !showElement"/>
</label>
Version 2:
<label class="form-switch">
<input type="checkbox" v-model="showElement"/>
</label>
Check this fiddle: https://jsfiddle.net/x4wykp2u/4/
Hope this makes sense
I have a straightforward XPage that lets a user answer a question with a simple Yes/No/NA response using radio buttons. I have restyled the radio buttons to look like a bootstrap button group to make it visually more interesting for the user. If the user chooses "Fail" then they are informed that they need to do something else - easily done with a simple partial refresh to a div further down the page.
This all works fine.
The problem I'm having is that I'd like it so that when the user selects an option, I would like to add a new class of "active" to the selected option so that it highlights in a pretty colour. But for the life of me I can't get this to work and though I'm sure it's a straight forward problem, I can no longer see the wood for the trees.
My current (abridged) iteration of the radio button code is this:
<xp:div styleClass="btn-group item-result" id="edit-result" loaded="${Question.open}">
<xp:radio text="${lbl.kwPass1}" id="itemPass"
styleClass="btn btn-pass #{(item.itemResult eq '0')?'active':''}" groupName="itemResult"
selectedValue="1">
<xp:eventHandler event="onchange" submit="true"
refreshMode="partial" refreshId="actionAlert">
<xp:this.script><![CDATA[XSP.partialRefreshPost('#{id:edit-result}');]]></xp:this.script>
</xp:eventHandler>
</xp:radio>
<!-- other radio buttons -->
</xp:div>
<!-- other page compenents -->
<xp:panel id="actionAlert">
<!-- panel content and appropriate rendered value -->
</xp:panel>
This was attempting to do a chained partial refresh on the radio button container so that the EL would evaluate and apply/remove the 'active' style based on the document datasource ('item') value. I have also tried using dojo.addClass, dojo.removeClass, XSP.partialRefreshGet and other options. I don't mind what the solution is as long as it's efficient and works. I'd prefer not to move the actionAlert panel to within the same container as the radio buttons and I can't do a full page refresh because there are other fields which will lose their values.
Some notes:
I'm not using a RadioGroup control because it outputs a table and I haven't got around to writing my own renderer for it yet. Single Radio button controls work fine for what I need them to do.
I originally tried using the full Bootstrap solution of using "data-toggle='buttons'" (source) which sorts out applying the "active" style fine but then, inevitably, prevents the partial refresh from working.
the radio button styles are clearly not Bootstrap standard
Any assistance pointers or, preferably, working solutions would be appreciated.
You need to aim your partial refresh at the div containing all your radio buttons. Give it an id, so you can address it.
Partial refresh, as the name implies, refreshes one element and its content only. So you target the element that covers all of the items you need to recompute.
Stepping away from the problem, a couple of beers and an episode of iZombie later, I realized what I was doing wrong and sorted it out. So, for posterity, here is the simple solution that I swear I tried earlier but clearly works now:
<xp:div styleClass="btn-group item-result" id="edit-result" loaded="${Question.open}">
<xp:radio text="${lbl.kwPass1}" id="itemPass" value="#{item.ItemResult}"
styleClass="btn btn-pass" groupName="itemResult" selectedValue="1">
<xp:eventHandler event="onchange" submit="true" refreshMode="partial" refreshId="actionAlert">
<xp:this.script><![CDATA[dojo.query('.item-result > .btn').removeClass('active');
dojo.query('.btn-pass').addClass('active');]]></xp:this.script>
</xp:eventHandler>
</xp:radio>
<!-- et cetera -->
The many places I was going wrong:
In my code in the question, I was calling XSP.partialRefreshPost in the CSJS script of the radio button when it should have been in the onComplete of the eventHandler. It has to be chained to another partial refresh so that it runs after it, not at the same time. I did end up getting this right - but overlooked something I'll come to in point 3.
In my original attempt to use Dojo, my first mistake was to try and target the ID of the radio button, something like:
dojo.addClass(dojo.byId('#{id:radio2}'),'active');
This actually works as expected, so long as you remember that the ID of the radio button on the XPage refers to the actual radio button control and not the label wrapping; and the label is what I wanted to style. So the class "active" was being actually being added, just not to the element I thought it was. I should have spotted this in my browser code inspector except for the third thing I got wrong:
Ironically, I sorted out the first issue, remembering to put the XSP.partialRefreshPost into the onComplete - and then didn't remove it when trying to run the Dojo.addClass(). So I didn't notice the mistake with the addClass targeting the wrong element because after it ran, the partial refresh updated the container and removed the class I had just added which made me think that nothing was working.
So now I have some neatly styled radio buttons that don't look like radio buttons and it's all managed client side without any unnecessary partial refresh trips to the server barring the one where I actually need to look stuff up from the server. And the vital lesson is - sometimes you just need to step away from a problem and come back to it with fresh eyes later on.
This is my very first Angular 2 project. I created a component (category) that would pull a list of categories from a service stack API and show as a dropdown like this:
<select (change)="onSelect($event.target.value)" [(ngModel)]="selectedCategory.Id">
<option *ngFor="let category of categoriesToDisplay"
value={{category.Id}}>{{category.Name}}
</option>
</select>
Selected Category is: {{selectedCategory.Id}} and Name is {{selectedCategory.Name}}
I have another component (AddExpense) which is a form, where the user can add in the amount, category and hit submit that would POST to another endpoint. For AddExpense component, this is how the .html looks
<form [formGroup]="expense" (ngSubmit)="fileExpense($event)">
Spent <input type="number" formControlName="amt" />
for <input type="text" formControlName="name" />
on <input type="date" formControlName="transdate" />
and file it under category <show-category></show-category>
<button type="submit">Add Expense</button>
</form>
My question is how do I figure out which category from the drop down was selected in the add expense form, when the drop down itself is rendered via the show-category component and pass it on as a form control item for add-expense component's .ts to use?
I might be needing to use the Input and output decorator, but not sure how to nab that particular item thats selected in the dropdown and pass it on as input to the add expense component.
Sounds like you're displaying your first component (ShowCategory) in the second (AddExpense).
Now there is a couple way to do this,
The most obvious is to use Output, ShowCategory will then emit (See EventEmitter and Output example) whenever the selected value is changed.
In the template of AddExpense, you'd simply have to write something like this,
<show-category (change)="category = $event.category"></show-category>
But that's ugly, and frankly it would've been cool if we can do this and let Angular handle the two-way binding,
<show-category [(ngModel)]="category"></show-category>
Turns out it's doable, you can check out documentation for NgModel here, but what's actually useful is an example implementation for a real control like a checkbox
You might've noticed in the example that NgModel is not mentioned anywhere, and that's because we only have to create the mechanism for NgModel to write/read value from your component.
If you search on Google for NgModel ValueAccessor, there's a bunch of blog posts to help you out.
Lastly, I personally doesn't suggest doing what you're doing now if the ShowCategory component is that simple, that increases complexity a little bit, and ShowCategory isn't doing much for now. But what you provided might very well be a minimum working example, so what do I know.
Happy coding!
In web page,there are few tabs like CustomerAccountContact.
These tabs are inside SPAN html tag.
I have added the web element for Account in OR. When I try to highlight it works fine but when I try to click using Click method its not going to the Account tab.
If I take the abs_x and abs_y of the web element and try to click using mercury.devicereply object it works fine.
PFB, the html source code for accounts tab:
<a class="x-tab-right" onclick="return false;" href="#">
<em class="x-tab-left">
<span class="x-tab-strip-inner">
<span class="x-tab-strip-text ">
Account
</span>
</span>
</em>
</a>
Since the link has an onclick="return false;" this means that click events don't do anything and the application reacts to different events. Apparently these events aren't those that UFT fires when it simulates a Click event.
You have two options as I see it.
Find out what event the application is reacting to and fire that event in the test (instead of performing a click)
Use device replay, this can be done more simply than using the Mercury.DeviceReplay object as you're doing by changing the replay-type to device (as explained in this answer).
It is occurring because application is firing different event. Even fire event may not work in this case. Since it is already working with Mercury device replay it would be better for you to create and register it (RegisterUserFunc).
RegisterUserFunc "WebLink", "fLnkClick", "fLnkClick"
Use:
Before click method
Setting.WebPackage("ReplayType") = 2
After click method
Setting.WebPackage("ReplayType") = 1
If you set Replay Type = 2 then you are giving control to Mouse, which do the actions similar the way you do manually. So clicks, mouseover and other mouse related actions will work if normal QTP click fails.
Also we can use "Mercury.DeviceReplay" object for the implementing similar logic.
I need to be able give users a link to my site with a parameter that will control their experience on the destination page, but, of course, Moqui does not allow parameters to be passed as a GET transaction. What are ways that I can work around that? It needs to be something that can be sent in an email, via sms and audibly.
An error message would be helpful know exactly what you are running into, but it sounds like the constraint to mitigate XSRF attacks.
The error message for this situation explains the issue and the recommended solution: "Cannot run screen transition with actions from non-secure request or with URL parameters for security reasons (they are not encrypted and need to be for data protection and source validation). Change the link this came from to be a form with hidden input fields instead."
You can pass URL parameters to screens to be used in code that prepares data for presentation, but not to transitions for code that processes input. The solution is to use a hidden form with a link or button to submit the form (that can be styled as a link or button or however you want). This is slightly more HTML than a plain hyperlink with URL parameters, but not a lot more and there are examples in various places in the Moqui itself.
If you are using an XML Screen/Form you can use the link element to do this with the #link-type attribute set to "hidden-form" or "hidden-form-link" (which just uses a hyperlink styled widget instead of a button styled one). If the #link-type attribute is set to "auto" (which is the default) it will use a hidden-form automatically if link goes to a transition with actions.
In plain HTML one possible approach looks something like this:
<button type="submit" form="UserGroupMemberList_removeLink_0">Remove</button>
<form method="post" action=".../EditUserGroups/removeGroup" name="UserGroupMemberList_removeLink_0">
<input type="hidden" name="partyId" value="EX_JOHN_DOE">
<input type="hidden" name="userGroupId" value="ADMIN">
</form>
Note that the button element refers to the form to submit, so can be placed anywhere in the HTML file and the form element can be placed at the end or anywhere that is out of the way (to avoid issues with nested forms which are not allowed in HTML).