The use of *ngIf in ionic 2 and ion-select dynamic


#1

hi guys , i am so confused about how to use ngif . I know its something to hide and show elements…
lets saying that I have an item and covered it with div tags
and in these tags I added ngIf

     <div *ngIf="showThis">
       <ion-select [(ngModel)]="courses" multiple="true">
          <ion-option>Math</ion-option>
          <ion-option>English</ion-option>
       </ion-select>
     </div>

how do you I call this (showThis) in .ts side in order to make it work…
What Im actually doing is this… I need ion-select in part of my application to show options which can multiply be selected… the button that should call this activity is action sheet:

   let actionSheet = this.actionsheetCtrl.create({
  
  title: 'Modify ' + param.name,
  cssClass: 'action-sheets',
  buttons: [
    {
      text: 'Add course',
      icon: !this.platform.is('ios') ? 'add-circle': null,
      handler: () => {
        
      }
    },

How do I call it in the handler so that ion-select shows… Also my Options are supposed to be dynamic

   this.schoolAppUsers.loadAllCourses().subscribe(response => {
               this.response = courses;
         }

How do I make it dynamic , and when returning back the selected items , it should be saved back to the server!!

can someone please help! I am stuck on this for a while now , much appreciated , thanx


Alert checkboxes do not show labels!
#2

@yasirpanjsheri What you can do:

1) To show the ion-select:

this.schoolAppUsers.loadAllCourses().subscribe(response => {
    this.courses = response;
    this.showThis = true;
}

Have in mind that you need to add courses: Array<any> and showThis: boolean to your component class.

2) In the HTML:

<div *ngIf="showThis">
	<ion-select [(ngModel)]="selectedCourses" multiple="true">
		<ion-option *ngFor="let course of courses" [value]="course.id">{{ course.name }}</ion-option>
	</ion-select>
	<button ion-button full (click)="onClick()">Save</button>
</div>

And create selectedCourses: Array<any> in your component class.

Read the docs for more info: https://ionicframework.com/docs/v2/api/components/select/Select/

I don’t think that you can add HTML to alerts, so I put a button to save the data.

(Replace course.id and course.name with a course identificator and the course name, respectively, according to the properties in your Course object).

3) Then create the method in the component:

onClick() {
    console.log('selectedCourses', this.selectedCourses);
    //TODO: send to the server
}

To send to the server, you can use Angular2 Http: https://angular.io/docs/ts/latest/tutorial/toh-pt6.html

But in the end you still have to read some docs and try to implement it yourself to make it work according to your needs :wink:


#3

Thank you for your explanation…much appreciated my friend… I am a little bet familiar with the http. I can post a value back to server and vice versa, but when it came to this multiple selection , I don’t know what approach should be taken. for example , this what I use to store back a single course:

 insertStudentCourse(UserID, course): Observable<User>{
 let headers = new Headers({'Content-Type':'application/x-www-form-urlencoded'});
 let options = new RequestOptions({headers:headers});
 return this.http.post(`${this.userApiUrl}/insertStudentCourse.php`,'userid='+UserID+'&course='+course, options)
  .map(res => <User>(res.json()))
 } 

it takes 2 param: User id and course name
but in here the user selects multiple values that should be stored at once. What approach should I take!


#4

@yasirpanjsheri In that case I use post with a JSON object in the body, so instead of:

'Content-Type': 'application/x-www-form-urlencoded'

I would use:

'Content-Type': 'application/json'

And the call would be: this.http.post(url, JSON.stringify({ userId, selectedCourses }), options)

Just have in mind that in the server you should handle the body as a JSON, but JSON is well supported in several languages, and although I’m not very familiar with PHP I think that would be something easy to do.

If you still want to use 'application/x-www-form-urlencoded', you can join the courses ids with some separator, like: '&courses=' + selectedCourses.join('+') and separate the values in the server, but I prefer the JSON approach.


#5

hi lucas , thank you for taking the time to relpy.

At first this how I put the post:

   login(login): Promise<User> {

let body = JSON.stringify({ username: login.username , password: login.password });  
let headers = new Headers({ 'Content-Type': 'application/json' });
let options = new RequestOptions({ headers: headers });

return this.http.post(this.loginApiUrl, body , options)
  .toPromise().then(res => <User>(res.json()))        
}

but it didn’t work out, I tried passing to the server but no response , even though the server side php handles the body as JSON , or at least I think it does.

  <?php

   header("Content-Type: application/json");
   $response = array();
   $username = $_POST['username'];
   $password = $_POST['password'];

     if ($_SERVER['REQUEST_METHOD']=='POST')
      {

	require_once 'DbOperation.php';

	$db = new DbOperation();

	$result = $db->userLogin($username, $password);

	if($result){

		$user = $db->getUserData($username);

		while($row = $user->fetch_assoc()){	
			$temp=array();
			$temp['error'] = "false";
			$temp['UserID'] = $row['UserID'];
			$temp['name'] = $row['name'];
			$temp['username'] = $row['username'];
			$temp['password'] = $row['password'];
			$temp['role'] = $row['role'];

			array_push($response,$temp);
		}
	} 
	else {
			$temp=array();
			$temp['error'] = "true";
			$temp['message'] = "Invalid username or password!";
			array_push($response,$temp);	
	}	
	echo json_encode($response);	
      }

and BTW, I am constructing the objects inside an array:
[ object, object , object] // array_push($response,$temp);

and accessing it from .ts like this
res[0].CourseName; // for example

the observable/promise returns an error of iteration if I dont have the objects in [0] position array!! My question, is this how observables work with JSON data?


#6

@yasirpanjsheri I think that your case there is a bit different (you want to send data to login, and receive user data as the response).

First, your PHP backend receive the data correctly? (the username and password is received, you can print it somehow so you know what you receive).

Second, The Observable/Promise will receive in the end what you sent in the server response. Like I said I’m not very familiar with PHP. If the PHP do the login correcly, then the response is what need to change.

If I understood correctly, your response is an array ($response = array();) and you are pushing data in it (array_push($response,$temp);). Shouldn’t your response be just 1 object (so $response = $temp). In your ts file it seems it should be a User object. I don’t know if I really understood your problem and if this solves it. If not, then maybe you should look in how you can return a JSON object in PHP in some PHP tutorial.

You can print the response in the ts file with console.log to help you know what is returned and (possibly) what needs to change.


#7

This is becoming a bit of a crusade for me. Especially with Ionic, which is really picky about DOM parent/child relationships when it comes to CSS selectors, I think people should do all they can to avoid creating unnecessary DOM elements like this <div>. Instead prefer:

<template [ngIf]="showThis">

#8

@rapropos I based my HTML in the original one, with minimum changes. But you are right, avoiding unnecessary DOM relationships is always welcome.