When list of search results is an object and one is chosen, ngtypeahead input shows [object][object] - ng-bootstrap

Model: {
"strText": "AngularJs",
"strSectionPath": "favoriteNpmLibraries",
"strTabPath": "angularJs"
}
If user choses this search result, then input box shows [object][object].
How can we fix this?

Use inputFormatter to choose what you want to display from an object.
In view:
<input [(ngModel)]="model" [ngbTypeahead]="search" [inputFormatter]="formatter" />
In component:
formatter = (x: {strText: string}) => x.strText;
It displays value of strText property of your object.
Let me know if you need more info.

Related

Chrome default MinLength Error

I have a input field through which users can submit some data.
But, if the data character length is less than 10, then they won't be able to submit.
<input type="text" minlength="10" placeholder="Submit" class="dataSubmit" />
Which means, in case a user tries to submit data with less than 10 characters then google chrome shows this error Please lengthen this text to 10 characters or more (you're currently using 3 characters).
But I want to change this error message to More data required.
So, how can I change this default message?
Thank You!
We can define the id for input and add custom validation using JavaScript.
<input id="data" type="text" minlength="10" placeholder="Submit" class="dataSubmit" />
In JavaScript, we can add custom validation for input something like below :
var data = document.getElementById("data");
data.addEventListener("input", function (event) {
if (data.validity.typeMismatch) {
data.setCustomValidity("Updated Error message");
} else {
data.setCustomValidity("");
}
});

knockoutjs creating new model from input elements?

jsFiddle: http://jsfiddle.net/Piercy/mD4kG/
So I have recently started working with knockout.js. I have started to get my head around it but am struggling with the following scenario.
I have the following model and view model structure:
function ViewModel() {
var self = this;
self.Emails = ko.observableArray([]);
self.AddEmail = function() {
// make ajax call here
self.Emails.push(new EmailModel(data));
};
}
function EmailModel(data) {
this.Id = data.Id;
this.Name = data.Name;
this.Subject = ko.observable(data.Subject);
this.DisplayId = ko.observable(data.DisplayId);
}
I want the ViewModel.Emails array to be an array of EmailModel's and my problem is how to create a new model to insert.
I imagine something like this:
<select data-bind="options: Emaillistdata, optionsText: 'Name', optionsValue: 'Id', optionsCaption: 'Choose...', value: DisplayId"></select><br /><br />
<input type="text" data-bind="value: Name"/><br />
<input type="text" data-bind="value: Subject"/><br />
<button data-bind="click: AddEmail">Add Email</button>
However, doing this would mean the the Name,Subject and DisplayId bindings would need to be in the ViewModel (which they are not). Also, it seems odd that I would have to add these to the ViewModel. I am kind of expecting to able to click the button and have a data variable that i can just do data.Name, data.Subject and data.DisplayId and have these variables not bound to any model, they are just submitted because i've named them as such or something? Then i can add them to the array and make them part of the ViewModel.
I could do all this with standard JS and then add it to the model but that also seems odd when everything else is using knockout. However maybe this is the answer?
jsFiddle: http://jsfiddle.net/Piercy/mD4kG/
Without knowing what you are trying to achieve from a UX point of view im not sure what your trying to achieve.
Have you looked at this ko tutorial. It shows you how to structure your code to be able to add new items
http://learn.knockoutjs.com/#/?tutorial=collections

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

TextBoxFor producing a blank field

I have a weird problem in my MVC app.
When the user selects a date from a drop down, it clears the StartDate and EndDate fields.
I have the following fragment of code:
<label>Start date: #Model.StartDate</label>
#Html.TextBoxFor(s => s.StartDate)
The weird thing is that you can wee where I'm outputting it in the label, the date comes out there. The textbox is unpopulated.
I've checked the produced markup and the textbox is not being populated.
<label>Start date: 19/05/2013</label>
<input id="StartDate" name="StartDate" type="text" value="" /> <br />
What am I missing here?
To add a little bit more information, when the page is initially populated the default start and end date are output. There is a bit of jQuery that empties those fields when a <select> is changed. If I comment that bit out then the fields retain their previous values as opposed to blank. Essentially, whatever is submitted to the server is output rather than the value in the model.
Essentially, whatever is submitted to the server is output rather than the value in the model.
This behaviour is actually by design. The idea being that generally the user would expect to see in the text box what they submitted to the server.
See here for a detailed explanation, and a work around.
Instead of doing this
<label>Start date: #Model.StartDate</label>
#Html.TextBoxFor(s => s.StartDate)
You should do this
<label id="someId"></label>
#Html.TextBoxFor(s => s.StartDate,new{#id="startdate"})
and using jquery on change event on your textbox you can set lablel
$("#startdate").change(function(){
var date="Start Date:"+$(this).val();
$("#someid").html(date);
});
Thinks that your model is a class named What like this:
public class What
{
public string StartDate { get; set; }
}
Then, think that your application is "MyApplication", you need to add to the view as if the view is stronglytyped:
#using MyApplication.Models;
#inherits System.Web.Mvc.WebViewPage<What>
Then all should we run as you expect

Search wordpress using three different drop down menus

I have three drop down menus that are chained together. Year, Make Model. I need wordpress search results to show their matching results. If I give them all the name="s" then it only searches the final s= in the url.
I basically need to know how to make
mysite.com/?s=2001&s=Chevrolet&s=Express&Search=Search
turn into:
mysite.com/?s=2001+Chevrolet+Express&Search=Search
or whatever gets the job done.
Any suggestions?
I would not name the selects. Instead, give them ids and make a hidden form field, then use javascript to update the hidden field.
function updateHiddenField(){
var year = document.getElementById("YearDD").value; //this is conceptual
var make = document.getElementById("MakeDD").value; //this is conceptual
var model = document.getElementById("ModelDD").value; //this is conceptual
document.getElementById("s").value = year+"+"+make+"+"+model; //this is conceptual
}
Then later...
<input type="hidden" name="s" id="s" value="">
<select id="YearDD" onChange="updateHiddenField();">
...
Otherwise you could overwrite the "Submit" Button, generate your own query string/url and redirect the page.
Or, in a real dirty way, you could just search the string and convert "&s=" with "+".

Resources