Birbirine Bağlı ComboBoxları AngularJS ve WebApi Kullanarak Doldurma
Selamlar;
Bugün bana birçok sefer sorulan birbirine bağımlı, yani biri seçilmeden diğerinin seçilemeyeceği “<select>” html elementlerinin AngularJs ve WebApi kullanılarak nasıl doldurulacağını hep beraber inceleyeceğiz.
Öncelikle Visual Stuio 2015’de bir WebApi projesi oluşturulur. İlgili comboları dolduran data modelleri aşağıdaki gibidir: İlk combo oyun konsolu(Console) seçimidir. 2. combo seçilen oyun konsoluna göre oyunun belirlenmesidir(Game). Son combo seçilen oyuna göre satıldığı dükkanların(Shop) listesidir.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
public class Console { public int Id { get; set; } public string Name { get; set; } public decimal Price { get; set; } } public class Game { public int Id { get; set; } public string Name { get; set; } public int ConsoleID { get; set; } } public class Shop { public int Id { get; set; } public string Name { get; set; } public int GameID { get; set; } } |
Şimdi sıra geldi örnek olması amacı ile ilgili modellerin data ile doldurulmasına. Aşağıda “Consoles, Games ve Shops” listelerinin birbirine bağımlı olarak, dummy data ile nasıl doldurulduğu görülmektedir.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
public class GamesController : ApiController { Console[] Consoles = new Console[] { new Console { Id = 1, Name = "Xbox One", Price = 1500 }, new Console { Id = 2, Name = "PS4", Price = 1250 }, new Console { Id = 3, Name = "Ps3", Price = 800 } }; Game[] Games = new Game[] { new Game { Id = 1, Name = "GearsOfWar",ConsoleID= 1 }, new Game { Id = 2, Name = "HeartStone", ConsoleID=1 }, new Game { Id = 3, Name = "Fifa2016", ConsoleID=1 }, new Game { Id = 4, Name = "Mortal Kombat", ConsoleID=2 }, new Game { Id = 5, Name = "Street Fighter", ConsoleID=2 }, new Game { Id = 6, Name = "Hunter", ConsoleID=2 }, new Game { Id = 7, Name = "Limbo", ConsoleID=3 }, new Game { Id = 8, Name = "Bridge", ConsoleID=3 }, new Game { Id = 9, Name = "Shadow Warrior", ConsoleID=3 } }; Shop[] Shops = new Shop[] { new Shop { Id = 1, Name = "Shopto",GameID= 1 }, new Shop { Id = 2, Name = "Ebay", GameID=1 }, new Shop { Id = 3, Name = "Amazon", GameID=2 }, new Shop { Id = 4, Name = "Argos", GameID=2 }, new Shop { Id = 5, Name = "Gamespot", GameID=3 }, new Shop { Id = 6, Name = "Mall", GameID=3 }, new Shop { Id = 6, Name = "Virgin", GameID=4 }, new Shop { Id = 6, Name = "GameShop", GameID=5}, new Shop { Id = 6, Name = "Virtual Shop", GameID=6 }, new Shop { Id = 6, Name = "GameLand", GameID=7 }, new Shop { Id = 6, Name = "Sendit", GameID=8 }, new Shop { Id = 6, Name = "BuyBuy", GameID=9 } }; } |
Şimdi sıra geldi ilk sayfa yani “Index.cshtml” yüklenir iken aşağıda görüldüğü gibi Console datasını döndüren Get() methoduna:
1 2 3 4 5 |
// GET api/values public IEnumerable<Console> Get() { return Consoles; } |
İkinci olarak seçilen konsola göre oyunların listesinin çekilmesi aşağıdaki gibidir:
1 2 3 4 5 |
// GET api/values/5 public IEnumerable<Game> Get(int id) { return Games.Where(cat => cat.ConsoleID == id).ToList(); } |
Son olarak seçilen oyunlara göre dükkanların listesinin çekilmesi aşağıdaki gibidir:
1 2 3 4 |
public IEnumerable<Shop> GetShops(int GameId) { return Shops.Where(shp => shp.GameID == GameId).ToList(); } |
Yukarıda dikkat edilmesi gereken bir nokta da “id”‘ye göre 2 farklı Get() methodunun çağrılmasıdır. Bunun sağlanabilmesi için “App_Start/WebApiConfig.cs” altına aşağıdaki route tanımlamaları yapılmalıdır. Aksi halde ilgili methodlara Web Api üzerinden erişilemez.
WebApiConfig.cs:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
config.Routes.MapHttpRoute( name: "Api", routeTemplate: "api/{controller}", defaults: null ); config.Routes.MapHttpRoute( name: "ApiById", routeTemplate: "api/{controller}/{id}", defaults: null ); config.Routes.MapHttpRoute( name: "ApiByName", routeTemplate: "api/{controller}/{action}/{GameId}", defaults: new { action = RouteParameter.Optional } ); |
Web Api’de ValuesController.cs( Full):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 |
using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Net.Http; using System.Web.Http; namespace Services.Controllers { public class GamesController : ApiController { Console[] Consoles = new Console[] { new Console { Id = 1, Name = "Xbox One", Price = 1500 }, new Console { Id = 2, Name = "PS4", Price = 1250 }, new Console { Id = 3, Name = "Ps3", Price = 800 } }; Game[] Games = new Game[] { new Game { Id = 1, Name = "GearsOfWar",ConsoleID= 1 }, new Game { Id = 2, Name = "HeartStone", ConsoleID=1 }, new Game { Id = 3, Name = "Fifa2016", ConsoleID=1 }, new Game { Id = 4, Name = "Mortal Kombat", ConsoleID=2 }, new Game { Id = 5, Name = "Street Fighter", ConsoleID=2 }, new Game { Id = 6, Name = "Hunter", ConsoleID=2 }, new Game { Id = 7, Name = "Limbo", ConsoleID=3 }, new Game { Id = 8, Name = "Bridge", ConsoleID=3 }, new Game { Id = 9, Name = "Shadow Warrior", ConsoleID=3 } }; Shop[] Shops = new Shop[] { new Shop { Id = 1, Name = "Shopto",GameID= 1 }, new Shop { Id = 2, Name = "Ebay", GameID=1 }, new Shop { Id = 3, Name = "Amazon", GameID=2 }, new Shop { Id = 4, Name = "Argos", GameID=2 }, new Shop { Id = 5, Name = "Gamespot", GameID=3 }, new Shop { Id = 6, Name = "Mall", GameID=3 }, new Shop { Id = 6, Name = "Virgin", GameID=4 }, new Shop { Id = 6, Name = "GameShop", GameID=5}, new Shop { Id = 6, Name = "Virtual Shop", GameID=6 }, new Shop { Id = 6, Name = "GameLand", GameID=7 }, new Shop { Id = 6, Name = "Sendit", GameID=8 }, new Shop { Id = 6, Name = "BuyBuy", GameID=9 } }; // GET api/values public IEnumerable<Console> Get() { return Consoles; } // GET api/values/5 public IEnumerable<Game> Get(int id) { return Games.Where(cat => cat.ConsoleID == id).ToList(); } public IEnumerable<Shop> GetShops(int GameId) { return Shops.Where(shp => shp.GameID == GameId).ToList(); } } public class Console { public int Id { get; set; } public string Name { get; set; } public decimal Price { get; set; } } public class Game { public int Id { get; set; } public string Name { get; set; } public int ConsoleID { get; set; } } public class Shop { public int Id { get; set; } public string Name { get; set; } public int GameID { get; set; } } } |
Şimdi yeni bir Mvc projesi yaratıp solution’a ekleyelim. Öncelikle aşağıdaki paketleri NuGet’den indirelim. Burada angularJs javacript framework’ünü kullanarak ilgili comboboxları dolduracağız.
Aşağıda öncelikle angularjs ve jquery kütüpahaneleri sayfaya eklenmiştir. AngularJS kodları “<html>” tagları arasında “ng-app=’app'” ile tanımlı module arasında çalışmaktadır. AngularJS ile ilgili detaylı yazımı yandaki link‘den erişebilirsiniz. Sayfa yüklendiği zaman “Get()” methodu çalışmakta ve “GetConsoles” ile ilgili konsol kaydı json olarak çekilerek “$scope.Consoles” modeline doldurulmaktadır. Ayrıca konsol combosunda seçili eleman “$scope.selectedConsoles” parametresine atanmakta ve en başta “null” değer verilmektedir. Oyun kombosunun görünümü “$scope.isShow” parametresine bağlıdır. Ve daha henüz konsol seçilmediği için “false” değeri atanarak gizlenmesi sağlanmıştır.
Index.cshtml:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
<html ng-app="app"> <head> <script src="~/Scripts/angular.min.js"></script> <script src="~/Scripts/jquery-2.1.4.min.js"></script> <script> var app = angular.module('app', []); app.controller('Controller', function ($scope, $http) { $scope.isShow = false; $scope.selectedConsoles = null; $scope.Consoles = []; $http({ method: 'GET', url: '/Home/GetConsoles' }).success(function (result) { $scope.Consoles = result; }); }); </script> <meta name="viewport" content="width=device-width" /> <title>Index</title> </head> </html> |
Server side tarafı için öncelikle aşağıdaki paket NuGet’den indirilir.
Aşağıdaki namespace’ler HomeController.cs sayfasına dahil edilir.
1 2 3 4 5 6 7 |
using Newtonsoft.Json; using System; using System.Collections.Generic; using System.Net.Http; using System.Net.Http.Headers; using System.Threading.Tasks; using System.Web.Mvc; |
HomeController.cs tarafında ilk sayfa yüklenirken “script” tarafından çağrılıp, tüm konsolları çeken “GetConsoles()” methodu aşağıdaki gibidir: WebApi servisi “http://localhost:65330” url’inden yayın yapmaktadır. İlgili servis, “HttpClient” ile(“http://localhost:65330/api/Games”) url’inden asenkron olarak request çekip, dönen string datayı “Console” sınıfına convert edip “Json” olarak geri döndürür.
HomeController.cs/GetConsoles():
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
public async Task<JsonResult> GetConsoles() { var product = new List<Console>(); HttpClient client = new HttpClient(); client.BaseAddress = new Uri("http://localhost:65330"); client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); HttpResponseMessage response = await client.GetAsync("api/Games"); if (response.IsSuccessStatusCode) { var data = await response.Content.ReadAsStringAsync(); product = JsonConvert.DeserializeObject<List<Console>>(data); } else { //Something has gone wrong, handle it here } return Json(product,JsonRequestBehavior.AllowGet); } |
Index.cshtml/Konsol Combosu: İlk konsol combosu aşağdaki gibi “$scope.Consoles” modeline “ng-model” directive ile bağlanır. Bir diğer “ng-options” directive ile name ve value değerlerini, herbir Item için çeker ve ilgili listeyi doldurur. Herhangi bir eleman seçildiği zaman “ng-change” directive’i ile “GetGames()” angularjs methodu çağrılır.
1 2 3 4 5 6 7 |
<body> <div ng-controller="Controller"> <select ng-model="selectedConsoles" ng-options="item.Id as item.Name for item in Consoles" ng-change="GetGames()"> <option value="">Konsole Seçiniz</option> </select> </div> </body> |
“GetGames()” methodu aşağıdaki gibidir: Amaç seçilen konsol tipine göre oyun combosunu doldurmaktır. Bunun için HomeController’daki “GetGames()” methoduna request atılır. Parametre olarak consol combosundan seçilen eleman “$scope.selectedConsoles” değeri gönderilir. Dönen result “$scope.Games” parametresine atanır. Böylece “ConsoleID” parametresi ile ilgili oyun combosu doldurulacaktır. Bu arada seçili oyunu temsil eden “$scope.selectedGames”‘e null değeri atanır. “$scope.isShopShow=false” ile de dükkanlar combosunun gizlenmesi sağlanır. Request sonucu olumlu dönmüş ise “$scope.isShow=true” ile ilgili oyun combosu görünür hale getirilir.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
$scope.GetGames = function () { $scope.selectedGames = null; $scope.Games = []; $scope.isShopShow = false; //$scope.selectedShops = null; //$scope.Shops = []; $http({ method: 'GET', url: '/Home/GetGames', params: { ConsoleID: $scope.selectedConsoles } }).success(function (result) { $scope.Games = result; $scope.isShow = true; }); } |
HomeController.cs/GetGames(): Aşağıda client tarafında konsol seçildiği zaman buna bağlı oyunların web api servisinden çekildiği method görülmektedir. WebApi servisi “http://localhost:65330” url’inden yayın yapmaktadır. İlgili servis, “HttpClient” ile(“http://localhost:65330/api/Games/”+ConsoleID) url’inden asenkron olarak request çekip, dönen string datayı “Game” sınıfına convert edip “Json” olarak geri döndürür.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
public async Task<JsonResult> GetGames(int ConsoleID) { var games = new List<Game>(); HttpClient client = new HttpClient(); client.BaseAddress = new Uri("http://localhost:65330"); client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); HttpResponseMessage response = await client.GetAsync("api/Games/" + ConsoleID); if (response.IsSuccessStatusCode) { var data = await response.Content.ReadAsStringAsync(); games = JsonConvert.DeserializeObject<List<Game>>(data); } else { //Something has gone wrong, handle it here } return Json(games, JsonRequestBehavior.AllowGet); } |
Index.cshtml/Oyun Combosu: Oyun combosu aşağdaki gibi “$scope.selectedGames” modeline “ng-model” directive ile bağlanır. “ng-options” directive ile name ve value değerlerini, herbir oyun elemanı için çeker ve ilgili listeyi doldurur. Herhangi bir eleman seçildiği zaman “ng-change” directive’i ile “GetShops()” angularjs methodu çağrılır.
1 2 3 |
<select ng-model="selectedGames" ng-options="item.Id as item.Name for item in Games" ng-show="isShow" ng-change="GetShops()"> <option value="">Oyun Seçiniz</option> </select> |
“GetShops()” methodu aşağıdaki gibidir: Amaç seçilen oyun tipine göre dükkan combosunun doldurulmasıdır. Bunun için HomeController’daki “GetShops()” methoduna request atılır. Parametre olarak “GameID” için oyun combosundan seçilen eleman “$scope.selectedGames” değeri gönderilir. Dönen result “$scope.Shops” parametresine atanır. Böylece “GameID” parametresi ile ilgili shop yani seçilen oyunun satıldığı dükkanlar combosu doldurulacaktır. Request sonucu olumlu dönmüş ise “$scope.isShopShow=true” ile ilgili dükkan combosu görünür hale getirilir.
1 2 3 4 5 6 7 8 9 10 11 12 |
$scope.GetShops = function () { $scope.selectedShops = null; $scope.Shops = []; $http({ method: 'GET', url: '/Home/GetShops', params: { GameID: $scope.selectedGames } }).success(function (result) { $scope.Shops = result; $scope.isShopShow = true; }); } |
HomeController.cs/GetShops(): Aşağıda client tarafında oyun seçildiği zaman buna bağlı dükkanların web api servisinden çekildiği method görülmektedir. WebApi servisi “http://localhost:65330” url’inden yayın yapmaktadır. İlgili servis, “HttpClient” ile(“http://localhost:65330api/GetShops/”+GameID) url’inden asenkron olarak request çekip, dönen string datayı “Shop” sınıfına convert edilip “Json” olarak geri döndürür.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
public async Task<JsonResult> GetShops(int GameID) { var shops = new List<Shop>(); HttpClient client = new HttpClient(); client.BaseAddress = new Uri("http://localhost:65330"); client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); HttpResponseMessage response = await client.GetAsync("api/Games/GetShops/" + GameID); if (response.IsSuccessStatusCode) { var data = await response.Content.ReadAsStringAsync(); shops = JsonConvert.DeserializeObject<List<Shop>>(data); } else { //Something has gone wrong, handle it here } return Json(shops, JsonRequestBehavior.AllowGet); } |
Index.cshtml/Dükkan Combosu: Dükkan combosu aşağdaki gibi “$scope.selectedShops” modeline “ng-model” directive ile bağlanır. “ng-options” directive’i ile name ve value değerlerini, herbir dükkan elemanı için çeker ve ilgili listeyi doldurur.
1 2 3 |
<select ng-model="selectedShops" ng-options="item.Id as item.Name for item in Shops" ng-show="isShopShow"> <option value="">Dükkan Seçiniz</option> </select> |
Index.cshtml(Full):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 |
@{ Layout = null; } <!DOCTYPE html> <html ng-app="app"> <head> <script src="~/Scripts/angular.min.js"></script> <script src="~/Scripts/jquery-2.1.4.min.js"></script> <script> var app = angular.module('app', []); app.controller('Controller', function ($scope, $http) { $scope.isShow = false; $scope.isShopShow = false; $scope.selectedConsoles = null; $scope.Consoles = []; $http({ method: 'GET', url: '/Home/GetConsoles' }).success(function (result) { $scope.Consoles = result; }); $scope.GetGames = function () { $scope.selectedGames = null; $scope.Games = []; $scope.isShopShow = false; //$scope.selectedShops = null; //$scope.Shops = []; $http({ method: 'GET', url: '/Home/GetGames', params: { ConsoleID: $scope.selectedConsoles } }).success(function (result) { $scope.Games = result; $scope.isShow = true; }); } $scope.GetShops = function () { $scope.selectedShops = null; $scope.Shops = []; $http({ method: 'GET', url: '/Home/GetShops', params: { GameID: $scope.selectedGames } }).success(function (result) { $scope.Shops = result; $scope.isShopShow = true; }); } }); </script> <meta name="viewport" content="width=device-width" /> <title>Index</title> </head> <body> <div ng-controller="Controller"> <select ng-model="selectedConsoles" ng-options="item.Id as item.Name for item in Consoles" ng-change="GetGames()"> <option value="">Konsole Seçiniz</option> </select> <select ng-model="selectedGames" ng-options="item.Id as item.Name for item in Games" ng-show="isShow" ng-change="GetShops()"> <option value="">Oyun Seçiniz</option> </select> <select ng-model="selectedShops" ng-options="item.Id as item.Name for item in Shops" ng-show="isShopShow"> <option value="">Dükkan Seçiniz</option> </select> </div> </body> </html> |
HomeController.cs(Full):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 |
using Newtonsoft.Json; using System; using System.Collections.Generic; using System.Linq; using System.Net.Http; using System.Net.Http.Headers; using System.Threading.Tasks; using System.Web; using System.Web.Mvc; namespace TrigerCombo.Controllers { public class HomeController : Controller { // GET: Home public ActionResult Index() { return View(); } public async Task<JsonResult> GetConsoles() { var product = new List<Console>(); HttpClient client = new HttpClient(); client.BaseAddress = new Uri("http://localhost:65330"); client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); HttpResponseMessage response = await client.GetAsync("api/Games"); if (response.IsSuccessStatusCode) { var data = await response.Content.ReadAsStringAsync(); product = JsonConvert.DeserializeObject<List<Console>>(data); } else { //Something has gone wrong, handle it here } return Json(product,JsonRequestBehavior.AllowGet); } public async Task<JsonResult> GetGames(int ConsoleID) { var games = new List<Game>(); HttpClient client = new HttpClient(); client.BaseAddress = new Uri("http://localhost:65330"); client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); HttpResponseMessage response = await client.GetAsync("api/Games/" + ConsoleID); if (response.IsSuccessStatusCode) { var data = await response.Content.ReadAsStringAsync(); games = JsonConvert.DeserializeObject<List<Game>>(data); } else { //Something has gone wrong, handle it here } return Json(games, JsonRequestBehavior.AllowGet); } public async Task<JsonResult> GetShops(int GameID) { var shops = new List<Shop>(); HttpClient client = new HttpClient(); client.BaseAddress = new Uri("http://localhost:65330"); client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); HttpResponseMessage response = await client.GetAsync("api/Games/GetShops/" + GameID); if (response.IsSuccessStatusCode) { var data = await response.Content.ReadAsStringAsync(); shops = JsonConvert.DeserializeObject<List<Shop>>(data); } else { //Something has gone wrong, handle it here } return Json(shops, JsonRequestBehavior.AllowGet); } } public class Console { public int Id { get; set; } public string Name { get; set; } public decimal Price { get; set; } } public class Game { public int Id { get; set; } public string Name { get; set; } public int ConsoleID { get; set; } } public class Shop { public int Id { get; set; } public string Name { get; set; } public int GameID { get; set; } } } |
Yukarıdaki örnekde de görüldüğü gibi birbirine bağlı, açılır liste elemanları AngularJS Javascript Framework’ü kullanılarak ajax post ile ilgili datayı web api bir servisten çekip asenkron olarak yüklemektedir.
Geldik bir makalenin daha sonuna. Yeni bir makalede görüşmek üzere hoşçakalın.
Source Code: http://www.borakasmer.com/projects/TrigerCombo.rar
Source:
oo abi eline sağlık . abi web api token authentication konusunda bir makaleni bekliyorum .
Küçük bir katkı, hem oluşan hata gitmekte, hemde sunum tarafı daha düzgün olsun diye :)
var app = angular.module(‘app’, []);
app.controller(‘Controller’, function ($scope, $http) {
$scope.isShow = false;
$scope.isShopShow = false;
$scope.selectedConsoles = null;
$scope.Consoles = [];
$http({
method: ‘GET’,
url: ‘/Home/GetConsoles’
}).success(function (result) {
$scope.Consoles = result;
});
$scope.GetGames = function ()
{
$scope.selectedGames = null;
$scope.Games = [];
$scope.isShopShow = false;
if ($scope.selectedConsoles != null)
{
$http({
method: ‘GET’,
url: ‘/Home/GetGames’,
params: { ConsoleID: $scope.selectedConsoles }
}).success(function (result) {
$scope.Games = result;
$scope.isShow = true;
});
}
else {
$scope.isShopShow = false;
$scope.isShow = false;
}
}
$scope.GetShops = function () {
$scope.selectedShops = null;
$scope.Shops = [];
if ($scope.selectedGames != null)
{
$http({
method: ‘GET’,
url: ‘/Home/GetShops’,
params: { GameID: $scope.selectedGames }
}).success(function (result) {
$scope.Shops = result;
$scope.isShopShow = true;
});
}
else {
$scope.isShopShow = false;
}
}
});
Bir formum var. İçerisinde ülke il ve ilçe birbirine bağlı. Servisten veri alıyorlar. Form u taslak olarak kaydedip daha sonra formu açtığımda seçtiğim verilerin gelmesini istiyorum. Nasıl yapabilirim ?