Focus next focusable element after dropdown selection in Vue 3 - vuejs3

I have a Vue 3 invoicing app using composition api.
In the invoice table I have a filterable dropdown for product selection.
Here is the part of the table code,
<tr v-for="(item, index) in items">
<td data-label="No" class="text-center">{{ index + 1 }}</td>
<td data-label="Item">
<Dropdown
v-model="item.product"
:options="products"
:disabled="item.disabled"
option-label="product_name"
:filter="true"
#change="onProductChange(index, $event)"
/>
</td>
<td data-label="Quantity">
<InputNumber
v-model="item.quantity"
class="input-text-right"
mode="decimal"
:min-fraction-digits="2"
:max-fraction-digits="2"
/>
</td>
</tr>
I have to make this invoice table completely keyboard accessible without the need to use a mouse
Everything works fine until a select a product in the dropdown. Once I select a product, the focus should go to quantity input automatically. Now it goes back to the very first focusable element on the page, which is the nav menu.
I tried emit to trigger tab press programatically and #blur to focus the next item. Nothing seems to be working.
I'm using PrimeVue components. Checked the docs. Nothing helpful there as well.
Could anyone help me please? Thank you!

add a ref to the quantity input, then in your onProductChange method you can focus that input
<InputNumber
ref="qtyInput"
v-model="item.quantity"
class="input-text-right"
mode="decimal"
:min-fraction-digits="2"
:max-fraction-digits="2"
/>
this.$refs.qtyInput will be an array of all inputs with that matching ref created by the v-for but since you already pass in the index you can use that to select the correct one and focus it.
onProductChange(index, event) {
this.$refs.qtyInput[index].focus();
}

Related

ngBootstrap Capture click event on typeahead suggestions

when I type 'ala' it displays 2 states in suggestions 'alabama' and 'alaska'. Now what I need is as soon as I click on 'alaska'/'alabama' any item in list it should call my method
methodAbc(){
//Some complex logic
alert("Method called.");
}
Sample code link click here
I tried blur, focus, etc events on text box they didnt work way I need. Click do not triggers on item selection it triggers when I click inside text box.
You just need to use the selectItem event from ng-bootstrap's ngbTypeAhead API
<input id="typeahead-template" type="text" class="form-control" [(ngModel)]="model"
[ngbTypeahead]="search" [resultTemplate]="rt" [inputFormatter]="formatter"
(selectItem)="methodABC($event)" />
See updated sample code

Angular: How to bind to an entire object using ng-repeat

I'm just beginning to experiment in Angular, and confused about how best to approach binding using ng-repeat. I basically get the point about ng-repeat creating a child scope. My problem is much more basic :) For html like this:
<div ng-controller="swatchCtrl" class="swatch-panel">
Swatches
<ul>
<li ng-repeat="swatch in swatchArray" class="swatch">
<input
type="radio"
name="swatches"
ng-model="$parent.currentSwatch"
value="{{swatch}}"
>
<label class="swatch-label">
<div class="swatch-color" style="background-color: #{{swatch.hexvalue}};"></div
><span class="swatch-name">{{swatch.colorName}}</span>
</label>
</li>
</ul>
currentSwatch is:
<pre>{{currentSwatch | json}}</pre>
currentSwatchObj is:
<pre>{{currentSwatchObj | json}}</pre>
how do I tell this to fire??
swatchArray is:
<pre>{{swatchArray | json}}</pre>
</div>
and javascript like this:
function swatchCtrl($scope) {
$scope.swatchArray = [
{colorName:'Red', hexvalue: 'ff0000', selected: 'false'},
{colorName:'Green', hexvalue: '00ff00', selected: 'false'},
{colorName:'Blue', hexvalue: '0000ff', selected: 'false'}
];
$scope.currentSwatch = {};
}
http://jsfiddle.net/8VWnm/
I want to:
a) When the user clicks on a radio button, I want it to set both the colorName and the hexvalue properties of the currentSwatch object. Right now the binding seems to be giving me a stringified object from the array. How do watch the return of currentSwatch so I can parse it back to an available object? Simple, I know, but what am I missing?
b) When the user clicks on a radio button, I think I want that to set the value of the corresponding "selected" key in the original array to "true". Vice versa for unchecking. Let's say that only one swatch can ever be selected at a time in the palette. (I would like in theory to be able to iterate through the array later on, on the supposition that the different keys and values are likely to sometimes not be unique.)
This kinda stuff is super easy with jquery methods, but I'd like to learn the idiomatic angular way. Thanks in advance for any help.
http://jsfiddle.net/8VWnm/54/
Instead of listening to the ng-click event I would set the index of the selected element to a variable called "currentSwatchIndex"
<li ng-repeat="swatch in swatchArray" class="swatch">
<input
type="radio"
ng-model="$parent.currentSwatchIndex"
value="{{$index}}"
>
</li>
The you can $watch value changes of the currentSwatchIndex in your controller and set the selected swatch-Object and selection states in this $watch function:
$scope.$watch('currentSwatchIndex', function(newValue, oldValue) {
$scope.currentSwatchObj = $scope.swatchArray[newValue];
$scope.swatchArray[newValue].selected = true;
$scope.swatchArray[oldValue].selected = false;
});
Only knowing the currentSwatchIndex should be enough to identify the selected swatchObject. So probably you can get rid of the currentSwatchObj and the selected property of your swatchArray.
You can always get the selected swatch programmatically through a array access.
For future users that can come here to do the same in a select, you don't need use any index, the select must be done like this:
http://docs.angularjs.org/api/ng.directive:select

Adding invoice lines with ASP.NET MVC

I'm creating ASP.NET applications with MVC 4 Technology, and I want to allow the end-user to enter line items onto an invoice. I want the user to have the ability to add as many line items as they wish to the invoice, and then when they are finished to be able to click the Save button on the form which would then write the invoice and all line item data to the database. Can somebody help guide me how to handle this?
This is the way I decided to do it after several other ideas failed me. It may sounds strange, but please bear with me. I used the MVC Index View as a basis.
Before the user even sees the Invoice, I add a new Invoice to the database so that I have an Invoice ID. I then display the Invoice Index View. But instead of the table showing #foreach (var item in Model) I changed it to #foreach (var item in Model.LineItems). Its blank now, but after I add some LineItsms I will be displaying a list of LineItems - which is exactly what an invoice is.
But we want to be able to add on our Invoice Index View as well. So at the top of the Index View, in the part where you can code, create a new LineItem and save its LineItem.invoiceID as the Model.ID. Then before you display the table of LineItems add a partial View - Create LineItem.
Now you have a list of Invoice Lines on a page where you can add new ones.
Here's some code from the Index View of LineItem:
#model MyAppName.Models.Invoice
#{
ViewBag.Title = "Index";
MyAppName.Models.LineItem line = new LineItem();
line.invoiceID = Model.ID;
}
<h2>Invoice</h2>
#Html.Partial("Create", line)
<table>
<tr>
<th>
#Html.DisplayName("Amount")
</th>
<th>
#Html.DisplayName("Description")
</th>
<th></th>
</tr>
#foreach (var item in Model.LineItems)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.Amount)
</td>
#Html.DisplayFor(modelItem => item.Description
</td>
<td>
#Html.ActionLink("Delete", "DeleteConfirmed", new { id = item.invoiceID })
</td>
</tr>
}
<tr>
<th>Total</th>
<th>R #Model.LineItems.Sum(amt => amt.Amount)</th>
<th></th>
<th></th>
</tr>
</table>
And here is what it looks like (except that mine was not an Invoice):
You want something like this. But it will be much more complex for your case. Use jquery to simplify your work.
$('#add_item').click(function() {
$('#invoice_listing tbody')
.append(
"<tr><td>" + $('#item').val() + "</td>" +
"<td>" + $('#amount').val() + "</td></tr>"
)
});
On every line item being added, the [Add Item] button will fire an event to do a ajax post of the line item data to the MVC controller. The controller will then do business logic and store the line item data into the database. Once the transaction is successful, the controller should return a "success" flag to the client browser. Use JSON for that will help. Your javascript should recognize the "success" flag, and add the item to the item listing.
Then finally, user will pressed on [Save] button, which complete the whole invoice data entry. You should then marked the invoice as successfully entered.
Try not to let user keep on adding the line item without being saved. They will be angry when saving failed after adding lines of item.
Have a popup where your users can search for the line items and add them. When selected capture the ItemId and use it to build a row, probably a tr or a div. So then you will have a tr or div for each line item that contains the Id of the line item and then one or two textboxes. Say a textbox for the quantity and another for the price. Then either do an ajax post where you iterate all the divs and put that info as a json data and post it to your controller method. Or format each div where your binding can collect them and be submitted when you do a postback - via your submit button. That should get you starting.

Radio Buttons are not applying style dynamically

I'm trying to refresh a list of radio buttons every time a user visits the tab menu. First time visit styling is okay, but they are behaving like checkboxes and can not be unchecked when other radio buttons are clicked.
I have tried to put refresh(); method but it still doesn't work.
You can see the demo on JSFIDDLE
Any suggestion? and Thank you.
$('.export_tab').click(function(){
$("#radios_wrapper").children().remove(); //Remove all previous radio buttons
for(var i in localStorage) //Looping through the localStorage
{
dataIndex = JSON.parse(localStorage[i]).index;
dataName = JSON.parse(localStorage[i]).name;
//Then insert a new one
$("#radios_wrapper").append('<input type="radio" value="'+dataIndex+'" name="'+dataIndex+'" id="radio'+dataIndex+'"/><label for="radio'+dataIndex+'">'+dataName+'</label>');
}
});
And this is the HTML
<div data-role="fieldcontain">
<fieldset data-role="controlgroup" id='radios_wrapper'>
</fieldset>
</div>
Radiobuttons need the same name to become a group. So:
'<input type="radio" value="'+dataIndex+'" name="'+dataIndex+'"/>'
is not the right way. The name should be the same for all radios you want to group. It should be:
'<input type="radio" value="'+dataIndex+'" name="allTheSame"/>'
Here is an update to your Fiddle.
To tell jQuery to redraw use the trigger function like .append('whatever').trigger('create'). http://jquerymobiledictionary.pl/faq.html. Updated Fiddle.

Strange behaviour on calender control (ToolTip)

I add Tooltips to a ASP.NET calendar control by code:
string newToolTip = string.Format(#"<div class='tooltip'><div class='toolHead'>{0}</div><div class='toolDate'>{1}-{2}</div></div>",sEvent.Title, sEvent.FromDate, sEvent.ToDate);
e.Cell.ToolTip = newToolTip;
e.Cell.Attributes.Add("OnClick", string.Format("javascript:__doPostBack('Karl Ender','{0}')", sEvent.Title));
Where "e" is a DayRenderEventArgs :
Calendar.DayRender += new DayRenderEventHandler(SpecialDayRender);
At the first Load of the page everything works fine, resulting in the following (correct) html-code:
<td title="" class="calendarcell" align="center" onclick="javascript:__doPostBack('Karl Ender','Hallo Welt')" style="color:White;background-color:Silver;width:14%;">7<div class="tooltip"><div class="toolHead">Hallo Welt</div><div class="toolDate">11/7/2012-5/9/2013</div></div></td>
When I change the month (or do another partial Postback) in the Calendar Control suddenly the Html-Code gets dizzy:
<td title="<div class='tooltip'><div class='toolHead'>Hallo Welt</div><div class='toolDate'>11/7/2012-5/9/2013</div></div>" class="calendarcell" align="center" onclick="javascript:__doPostBack('Karl Ender','Hallo Welt')" style="color:White;background-color:Silver;width:14%;">7</td>
So, the Tooltip gets rendered as a "Title"-Attribute of that Cell
Any clue?
(The calendar is within an updatePanel)
When debugging the code, the Title-Attribute of a cell is never filled with that strange content

Resources