checking values on (click) button or at <ion-input> - ionic-framework

Good evening,
***<ion-item>
<on-input type="integer" placeholder="integer value" clearInput="true" [(ngModel)]="myinput"></ion-input>
</ion-item>
<ion-item>
<button ion-button (click) ="addmesurement()" color="light">***
I just need to make sur that myinput is not null before calling the function addmesurement. is there any contole i can add in <ion-put> like "Not null" for example.
i found some suggestions for some problems like mine but the solutions are a litte bit old and complicated. does ionic3/4 provide any solution easy to implement ?

I think it will be far better to make that check down in the function addmesurement or make a new function in the ts file:
addmesurementWithCheck() {
if (!this.myinput) return;
this.addmesurement();
}
and then call this function from your button in the html-file

Related

How to change color of input range slider with tailwind css?

Wish you are having a wonderful day,
I'm currently trying to apply some color to a simple slider range.
<Input class="range pr-6 bg-red-500"
type="range"
value="0" min="0"
max="1000"
onChange="rangeSlide(this.value)"
onmousemove="rangeSlide(this.value)"></Input>
It doesn't work at all to change the color like this, I also tried with text and border class.
I made some research and assume I should use this to change the slider bar : -webkit-slider-thumb
Like this :
.range::-webkit-slider-thumb {
background: #00fd0a;
}
However I wish to only use tailwind and dont apply style with pure css. if anyone have any insight to give me I would really appreciate it.
Here is what works for me, using accent-<color>-<number> :
<Input class="range pr-6 accent-red-500"
type="range"
value="0" min="0"
max="1000"
onChange="rangeSlide(this.value)"
onmousemove="rangeSlide(this.value)"></Input>
Also, link to the documentation if someone pass by and need more info : https://tailwindcss.com/docs/accent-color

Ionic - Limits of what can be pushed into [innerHTML]

I'm a volunteer at a Coffee Shop. I've built an app that presents the drink recipe to the barista. Here's a quick snapshot:
The data come from a firebase realtime database. Here's a snippet from that database:
What I want to do is to put some HTML into the instructions to format it for easy reading. I do that by binding the content in the template file to [innerHTML] as shown below:
<ion-item>
<ion-grid>
<ion-row *ngIf="!item.temperature">
<ion-col>
<ion-label><strong>Instructions</strong></ion-label>
</ion-col>
</ion-row>
<ion-row>
<ion-col>
<h5 *ngIf="this.compactMode">
<span [innerHTML]="item.instructions"></span>
</h5>
<span *ngIf="!this.compactMode" [innerHTML]="item.instructions">
</span>
</ion-col>
<ion-col *ngIf="item.image"
><ion-img
(click)="onClickImage(item.image)"
src="{{item.image}}"
></ion-img
></ion-col>
</ion-row>
</ion-grid>
</ion-item>
THE PROBLEM
This works really well for <b> <ol> <ul> <li> <br> and so on. But it does not work for <ion-checkbox> nor <input type="checkbox"> The input tags get filtered out somewhere before being presented.
SECURITY
I'm aware that putting HTML into a database can increase my security surface, so I'm using sanitizer to filter the HTML and then I attempt to add the after the fact. Here's how I do it:
stringFormat(inputString: string) {
const re1 = /\[\]/gi;
let returnString = this.sanitizer.sanitize(1, inputString);
returnString = returnString.replace(re1, '<ion-checkbox id=\'input\'></ion-checkbox>');
return returnString;
}
You'll notice that I first sanitize the string, and then I do a substitution, replacing [] with the checkbox.
(In case you're interested, I'm just making a opening/closing checklist and it would be nice if people could touch the checkbox after they've completed a task... I don't plan to store the checkbox values, I just want the checkbox user experience.)
I have checked that item.instructions in fact includes the substituted string in the item object, but when rendered by ionic/angular, the actual text seems to have filtered out anything but vanilla HTML tags.
Finally the Question
So here's the question: Are there some sort of limits to what can be inserted into the DOM using [innerHTML] binding? Am I overthinking this?
Thanks.
After reading https://developer.mozilla.org/en-US/docs/Web/API/Element/innerHTML, I've concluded that there really is not a safe way to do this using the approach suggested above.
Instead of embedding HTML in the database, I'm going to set up an array of paragraphs in the item.instructions fields of the database. Each element in the array can have a key:value pair to indicate if the element represents a plain paragraph, or a checkbox.
Then I can iterate through the array of instructions (*ngFor), and for each instruction I can check the instruction type (<div *ngIf="item.type===...>) to determine whether to wrap the text with an <ion-text> or an <ion-checkbox>.

Why does Ionic components render the <Host> and then inside, the <TagType>, instead of just rendering the <TagType>?

Refering to the documentation for a Ionic button component I see that the component renders the <Host>, and then, inside the <TagType>. I would like to know what is the reason behind.
For example, why not just rendering the <TagType> ?
Along with this question, I also see that all the classes are attached to the <Host>, instead of to the <TagType>. I would also like to know what is the reason behind this. Why not adding the classes directly to the <TagType> ?
This is the tsx for the Ionic button component :
return (
<Host
onClick={this.handleClick}
aria-disabled={disabled ? 'true' : null}
class={{
...createColorClasses(color),
[mode]: true,
[buttonType]: true,
[`${buttonType}-${expand}`]: expand !== undefined,
[`${buttonType}-${finalSize}`]: finalSize !== undefined,
[`${buttonType}-${shape}`]: shape !== undefined,
[`${buttonType}-${fill}`]: true,
[`${buttonType}-strong`]: strong,
'button-has-icon-only': hasIconOnly,
'button-disabled': disabled,
'ion-activatable': true,
'ion-focusable': true,
}}
>
<TagType
{...attrs}
class="button-native"
disabled={disabled}
onFocus={this.onFocus}
onBlur={this.onBlur}
>
<span class="button-inner">
<slot name="icon-only"></slot>
<slot name="start"></slot>
<slot></slot>
<slot name="end"></slot>
</span>
{mode === 'md' && <ion-ripple-effect type={this.rippleType}></ion-ripple-effect>}
</TagType>
</Host>
);
and This is how it gets rendered :
<ion-button size="small" class="ios button button-small button-solid ion-activatable ion-focusable hydrated">Default</ion-button>
#shadow-root
<button type="button" class="button-native">
<span class="button-inner">
<slot name="icon-only"></slot>
<slot name="start"></slot>
<slot></slot>
<slot name="end"></slot>
</span>
</button>
As you can see, the classes are inserted on the Host (ion-button), instead of on the <TagType>. I would like to understand what benefit lies behind this decission.
Also, I would like to understand what is the reason for having a <span class="button-inner"> inside the <TagType> (button) ? Why not just throwing the <slot></slot> directly into the <TagType> ?
I am new to Stencil and Ionic, and I am very eager about understanding the best possible way to build components. So, I would be much appreciated if anyone can kindly help me understand the reasons that lies behind this descisions!
Host is used to add classes, event listeners, and attributes on the ion-button it self, and not any nested DOM of the component. This is because when doing things like class bindings, we only really care about the element itself, not the internals of the components. With cross-component communication and shadow DOM, it's not possible to get internal references to things like TageType in this situation.
And the reason for the slot is to handle cross browser differences in how text/styles are applied for buttons. More internal knowledge for us at Ionic, and not things that others need to know about.

How to get the filename of a filepicker.io picture to appear in the input field next to it

I am trying to get the filename of an uploaded picture to appear in the input field next to the picker button (for filepicker.io) . Basically I am trying to find what to put in the value field for the input tag to get the filename to appear once the picture is uploaded. Here is the code I have:
<div class="row margin" id='img-row'>
<input id="filename" disabled="disabled" value="<WHAT DO I PUT HERE?>" class="input" type="text" style="width: 360px;"/>
<input name="img" data-fp-class="form-simple-action-btn filepicker_launcher" data-fp-button-text="Choose Image" data-fp-services="COMPUTER,FACEBOOK,FLICKR,INSTAGRAM,PICASA" data-fp-container="modal" data-fp-mimetypes="image/*" type="filepicker" data-fp-apikey="#################" id='campaign-img-input' value="<php echo h($_POST['img'])"/>
</div>
Thank you for your help! I haven't found any other examples like this in the documentation.
The recommended way to do this would be to bind a function to the onchange event of the filepicker input type. Once the upload occurs, the function will be called, and you can pull the filename out of the e.fpfile attribute.
Alternatively, it may be easier to use the filepicker.pick call directly given that you are interested in customizing the behavior. The widget is great for a drop-in solution in many cases, but if you're looking to customize further I'd recommend using the javascript api directly.

MVC3 and Razor - How to place a dynamic value for hidden field?

I'm a beginner about Razor, and sometimes I get stuck with really simple things.
I have this foreach loop:
#foreach (dynamic item in ViewBag.EAList)
{
<li>
#using (#Html.BeginForm("Duplicate, "Daily"))
{
<p>#item.AuthorComment</p>
#Html.Hidden("EstadoDeAlmaID", #item.EAID)
#Html.Hidden("PosterID", Session["id"].ToString())
<input type="submit" value="Send" />
}
</li>
}
This line:
#Html.Hidden("EstadoDeAlmaID", #item.EAID)
Doesn't work, and I don't know how to make it work, I tried many ways, without #, with (--), with #(--)...
Could someone help me to display the dynamic value in my hidden field?
In addition, if someone know about a good Razor samples websites, I would be very thankful.
I had the same problem, found that a simple cast solved my problem.
#Html.Hidden("id", (string) ViewBag.ebook.isbn)
In Razor, once you are in "C# land", you no longer need to prefix values with # sign.
This should suffice:
#Html.Hidden("EstadoDeAlmaID", item.EAID)
Check out Scott Gu's article covering the syntax for more help.
Update
And I would also move your <li></li> within your using block, as Razor works better when you wrap HTML blocks inside of a code blocks.
Also, your Html.BeginForm should live outside of your loop.
#using (#Html.BeginForm("Duplicate, "Daily"))
{
<ul>
#foreach (? item in ViewBag.EAList)
{
<li>
<p>#item.AuthorComment</p>
#Html.Hidden("EstadoDeAlmaID", item.EAID)
#Html.Hidden("PosterID", Session["id"].ToString())
<input type="submit" value="Send" />
</li>
}
</ul>
}
Where ? in the foreach loop is the type of your items in EAList.
To avoid the Extension methods cannot be dynamically dispatched exception, use a model instead of ViewBag so you will not be using dynamic objects (this will avoid all the unnecessary casting in the View and is more in line with MVC style in general):
In your action when you return the view:
return View("ViewName", db.EAList.ToList());
In your view, the first line should be:
#model IEnumerable<EAListItem> //or whatever the type name is
Then just do:
#foreach(var item in Model)
You got the error, "Extension methods cannot be dynamically dispatched"... therein lies your trouble.
You should declare you loop variable not to be of type dynamic, but of the actual type in the collection. Then remove the # from the item.EAID call inside the #Html.Hidden() call.
The simple solution for me was to use ViewData instead of ViewBag. ViewBag is just a dynamic wrapper around ViewData anyway.
#Html.Hidden("ReportID", ViewData["ReportID"])
but I don't know if this will help in your case or not since you are creating dynamic items in your foreach loop.
I have found that when i want to use the view bag data in the HTML
Getting back to basics has often worked for me
<input type="hidden" name="Data" id="Data" value="#ViewBag.Data" />
this gave the same result.