Flutter
GraphQL
Ejemplo CRUD en Flutter con GraphQL: Guía Completa SEO
18 min
ejemplo de aplicación crud en flutter utilizando graphql introducción en nuestra primera guía de flutter graphql, hemos aprendido cómo configurar un proyecto de flutter utilizando la api de graphql para conectar y consultar datos simples en back4app también, cómo podemos usar el playground de graphql de back4app para ejecutar consultas/mutaciones para crear/poblar la base de datos de la aplicación en este tutorial, añadiremos una función con la que crearemos, actualizaremos y eliminaremos datos de nuestro backend de back4app directamente desde nuestra aplicación utilizando mutaciones de graphql objetivos al final de este artículo, esperamos que puedas crear datos en nuestro backend utilizando la api de graphql actualizar datos de nuestro backend utilizando la api de graphql eliminar datos existentes del backend utilizando la api de graphql requisitos previos para completar este tutorial, necesitarás necesitarás leer nuestra guía anterior “proyecto flutter graphql” para entender nuestro punto de partida en esta guía vamos a usar el proyecto anterior, si no lo tienes puedes descargarlo aquí un ide para escribir código flutter como android studio o vs code una cuenta de back4app que se puede crear aquí dependencia back4app graphql flutter https //pub dev/packages/graphql flutter nota si deseas una mejor comprensión de la api graphql de back4app, echa un vistazo a nuestro libro de cocina graphql https //www back4app com/docs/parse graphql/graphql getting started y también revisa nuestro esquema graphql en nuestro api playground 1 configuración de la gui crea un nuevo archivo mutation page dart mutation page dart aquí crearemos nuestra gui para tomar entradas del usuario y realizar tareas de mutación ahora pega el siguiente código en mutation page dart mutation page dart 1 import 'package\ back4appgraphqldemo/app ui dart'; 2 import 'package\ back4appgraphqldemo/database utils dart'; 3 import 'package\ flutter/material dart'; 4 5 class mutationpage extends statelesswidget { 6 7 string langname,saveformat,objectid; 8 databaseutils utils; 9 10 @override 11 widget build(buildcontext context) { 12 return appui( 13 onchangedname (text){ 14 langname=text; 15 }, 16 onchangedsaveformat (text){ 17 saveformat=text; 18 }, 19 onchangedobjectid (text){ 20 objectid=text; 21 }, 22 senddatabuttonpressed (){ 23 }, 24 deletedatabuttonpressed (){ 25 }, 26 updatebuttonpressed (){ 27 }, 28 ); 29 } 30 } appui() appui() el widget ya ha sido creado para ti así que hemos creado una clase llamada mutationpage mutationpage y retornado el appui appui widget como su widget también hemos inicializado funciones de callback para nuestros campos de texto de tal manera que el texto en el primer campo de texto se almacenará en langname langname , el segundo en saveformat saveformat y objectid objectid del último ahora procede a main dart main dart y agrega un floatingactionbutton floatingactionbutton parámetro en scaffold() scaffold() widget de myhomepage myhomepage clase y pasa el siguiente código en él 1 floatingactionbutton row( 2 mainaxisalignment mainaxisalignment end, 3 children \[ 4 floatingactionbutton( 5 herotag 'mutation page', 6 child text('m', 7 style textstyle( 8 color colors white, 9 ), 10 ), 11 onpressed (){ 12 navigator pushreplacement(context, materialpageroute( 13 builder ((context){ 14 return mutationpage(); 15 }) 16 )); 17 }, 18 ), 19 ], 20 ), esto creará un botón flotante que nos llevará a la mutationpage() mutationpage() desde nuestra página de inicio así que ahora nuestra gui está configurada ahora puedes reiniciar tu aplicación para ver la gui así es como debería verse tu main dart main dart 1 import 'package\ back4appgraphqldemo/mutation page dart'; 2 import 'package\ flutter/material dart'; 3 import 'package\ graphql flutter/graphql flutter dart'; 4 import 'consonents dart'; 5 import 'dart\ ui'; 6 7 void main() { 8 runapp(myapp()); 9 } 10 11 class myapp extends statelesswidget { 12 @override 13 widget build(buildcontext context) { 14 final httplink httplink = httplink( 15 uri 'https //parseapi back4app com/graphql', 16 headers { 17 'x parse application id' kparseapplicationid, 18 'x parse client key' kparseclientkey, 19 'x parse master key' kparsemasterkey, 20 //'x parse rest api key' kparserestapikey, 21 }, //getheaders() 22 ); 23 24 valuenotifier\<graphqlclient> client = valuenotifier( 25 graphqlclient( 26 cache optimisticcache(dataidfromobject typenamedataidfromobject), 27 link httplink, 28 ), 29 ); 30 31 return materialapp( 32 home graphqlprovider( 33 child myhomepage(), 34 client client, 35 ), 36 ); 37 } 38 } 39 40 class myhomepage extends statefulwidget { 41 @override 42 myhomepagestate createstate() => myhomepagestate(); 43 } 44 45 class myhomepagestate extends state\<myhomepage> { 46 string name; 47 string saveformat; 48 string objectid; 49 50 string query = ''' 51 query findlanguages{ 52 languages{ 53 count, 54 edges{ 55 node{ 56 name, 57 saveformat 58 } 59 } 60 } 61 } 62 '''; 63 64 @override 65 widget build(buildcontext context) { 66 return safearea( 67 child scaffold( 68 appbar appbar( 69 title text( 70 'parsing data using graphql', 71 ), 72 ), 73 floatingactionbutton row( 74 mainaxisalignment mainaxisalignment end, 75 children \[ 76 floatingactionbutton( 77 herotag 'mutation page', 78 child text('m', 79 style textstyle( 80 color colors white, 81 ), 82 ), 83 onpressed (){ 84 navigator pushreplacement(context, materialpageroute( 85 builder ((context){ 86 return mutationpage(); 87 }) 88 )); 89 }, 90 ), 91 ], 92 ), 93 body query( 94 options queryoptions( 95 documentnode gql(query), 96 ), 97 builder ( 98 queryresult result, { 99 refetch refetch, 100 fetchmore fetchmore, 101 }) { 102 if (result data == null) { 103 return center( 104 child text( 105 "loading ", 106 style textstyle(fontsize 20 0), 107 )); 108 } else { 109 return listview\ builder( 110 itembuilder (buildcontext context, int index) { 111 return listtile( 112 title text(result data\["languages"]\["edges"]\[index]\["node"] 113 \['name']), 114 trailing text(result data\["languages"]\["edges"]\[index] 115 \["node"]\['saveformat']), 116 117 ); 118 }, 119 itemcount result data\["languages"]\["edges"] length, 120 ); 121 } 122 }, 123 ), 124 ), 125 ); 126 } 127 } 2 creando/agregando datos a la base de datos si procedes a graphql configration dart graphql configration dart podrías ver que ya hemos configurado nuestro graphqlclient graphqlclient y ahora podemos usarlo en cualquier lugar procedamos a crear un archivo database utils dart database utils dart y realizar una operación para crear datos crea una clase databaseutils{} databaseutils{} y crea un constructor que reciba los parámetros de datos con los que trabajaremos, aquí necesitaremos langname langname , saveformat saveformat , y objectid objectid 1 import 'package\ back4appgraphqldemo/graphql configration dart'; 2 import 'package\ graphql flutter/graphql flutter dart'; 3 4 class databaseutils{ 5 final string langname,saveformat,objectid; 6 databaseutils({this langname="",this saveformat="",this objectid=""}); 7 } crea una función adddata() adddata() que será una función asíncrona para crear datos e inicializar nuestro graphqlclient graphqlclient inicializando la clase graphqlconfigration graphqlconfigration pega el siguiente código en la función senddata() senddata() 1 future\<queryresult> senddata() async{ 2 string adddata=''' 3 mutation createobject(\\$input createlanguagefieldsinput){ 4 createlanguage(input {fields \\$input}){ 5 language{ 6 name, 7 saveformat 8 } 9 } 10 } 11 '''; 12 final variable ={ 13 "input" { 14 "name" langname, 15 "saveformat" saveformat, 16 } 17 }; 18 19 graphqlconfiguration configuration = graphqlconfiguration(); 20 graphqlclient client = configuration clienttoquery(); 21 22 } aquí hemos inicializado una variable adddata adddata y hemos pasado la consulta para crear datos e inicializado variable variable que pasará las variables de consulta también inicializamos el graphqlclient graphqlclient que nos ayudará a pasar consultas podemos pasar las consultas de la manera siguiente 1 queryresult queryresult = await client query( 2 queryoptions(documentnode gql(adddata), variables variable), 3 ); 4 return queryresult; usamos nuestra graphqlclient graphqlclient instancia para escribir una consulta que acepta queryoptions() queryoptions() que nos ayuda a enviar una consulta como has visto en el último tutorial el resultado se almacena en queryresult queryresult así es como debería verse tu database utils dart database utils dart 1 import 'package\ back4appgraphqldemo/graphql configration dart'; 2 import 'package\ graphql flutter/graphql flutter dart'; 3 4 class databaseutils{ 5 final string langname,saveformat,objectid; 6 databaseutils({this langname="",this saveformat="",this objectid=""}); 7 future\<queryresult> senddata() async{ 8 string adddata=''' 9 mutation createobject(\\$input createlanguagefieldsinput){ 10 createlanguage(input {fields \\$input}){ 11 language{ 12 name, 13 saveformat 14 } 15 } 16 } 17 '''; 18 final variable ={ 19 "input" { 20 "name" langname, 21 "saveformat" saveformat, 22 } 23 }; 24 25 graphqlconfiguration configuration = graphqlconfiguration(); 26 graphqlclient client = configuration clienttoquery(); 27 28 queryresult queryresult = await client query( 29 queryoptions(documentnode gql(adddata), variables variable), 30 ); 31 return queryresult; 32 } 33 } ahora procede a tu clase de ui mutation page dart mutation page dart vamos a codificar el botón de enviar datos que se puede codificar dentro del senddatabuttonpressed senddatabuttonpressed parámetro dado que necesitamos el langname y saveformat, primero verifica si no está vacío y luego crea una instancia de databaseutils databaseutils y pasa el langname langname y saveformat saveformat parámetro 1 if(langname isnotempty && saveformat isnotempty){ 2 utils = databaseutils( 3 langname langname, 4 saveformat saveformat , 5 ); 6 } después de esto, llama a la senddata() senddata() función de la databaseutils databaseutils instancia ahora puedes hot restart la aplicación, llena los dos campos de texto con sus respectivos datos y presiona el botón de enviar datos ahora regresa a tu página de consulta presionando el botón de acción flotante y podrás ver que se ha añadido un dato más a nuestra tabla así es como se vería tu clase mutationpage 1 import 'package\ back4appgraphqldemo/app ui dart'; 2 import 'package\ back4appgraphqldemo/database utils dart'; 3 import 'package\ flutter/material dart'; 4 5 class mutationpage extends statelesswidget { 6 7 string langname,saveformat,objectid; 8 databaseutils utils; 9 10 @override 11 widget build(buildcontext context) { 12 return appui( 13 onchangedname (text){ 14 langname=text; 15 }, 16 onchangedsaveformat (text){ 17 saveformat=text; 18 }, 19 onchangedobjectid (text){ 20 objectid=text; 21 }, 22 senddatabuttonpressed (){ 23 if(langname isnotempty && saveformat isnotempty){ 24 utils = databaseutils( 25 langname langname, 26 saveformat saveformat , 27 ); 28 utils senddata(); 29 } 30 }, 31 deletedatabuttonpressed (){ 32 }, 33 updatebuttonpressed (){ 34 }, 35 ); 36 } 37 } 3 actualizando datos en databaseutils databaseutils crea una future future función updatedata() updatedata() inicializa una string update string update y pasa la consulta de actualización y variables de consulta en final variables final variables 1 future\<queryresult> updatedata() async{ 2 string update=''' 3 mutation updateobject(\\$id id!,\\$input updatelanguagefieldsinput){ 4 updatelanguage(input {id \\$id, fields \\$input}){ 5 language{ 6 name, 7 id 8 } 9 } 10 } 11 '''; 12 final variable={ 13 "id"\ objectid, 14 "input" { 15 "name" langname 16 } 17 }; 18 } ahora inicializa nuestro graphqlclient graphqlclient y envía la consulta a través de queryoptions() queryoptions() así es como se vería tu código 1 future\<queryresult> updatedata() async{ 2 3 string update=''' 4 mutation updateobject(\\$id id!,\\$input updatelanguagefieldsinput){ 5 updatelanguage(input {id \\$id, fields \\$input}){ 6 language{ 7 name, 8 id 9 } 10 } 11 } 12 '''; 13 14 final variable={ 15 "id"\ objectid, 16 "input" { 17 "name" langname 18 } 19 }; 20 21 graphqlconfiguration configuration = graphqlconfiguration(); 22 graphqlclient client = configuration clienttoquery(); 23 24 queryresult queryresult = await client query( 25 queryoptions(documentnode gql(update), variables variable), 26 ); 27 return queryresult; 28 } ahora regresa a mutaion page dart mutaion page dart y codifica en el updatebuttonpressed updatebuttonpressed parámetro verifica si langname langname , objectid objectid y saveformat saveformat no están vacíos y luego llama a la updatedata() updatedata() función de databaseutils databaseutils clase 1 updatebuttonpressed (){ 2 if(langname isnotempty && saveformat isnotempty && objectid isnotempty){ 3 utils = databaseutils( 4 langname langname, 5 saveformat saveformat , 6 objectid objectid 7 ); 8 utils updatedata(); 9 } 10 }, ve al panel de control de back4app y elige un idioma para actualizar, luego copia su objectid reinicia rápidamente tu aplicación y llena los 3 campos de texto el nuevo nombre del idioma que deseas insertar en el primer campo de texto y el nuevo formato de guardado en el segundo y objectid en el tercero ahora presiona el botón de actualizar datos y verifica la información actualizada en la aplicación haciendo clic en el botón de acción flotante q en la esquina inferior derecha 4 eliminando datos crea una deletedata() deletedata() asíncrona función en databaseutils databaseutils e inicializa string delete string delete y pasa la consulta graphql para eliminar datos toma variables finales variables finales y pasa las variables de consulta en ella 1 future\<queryresult> deletedata() async{ 2 string delete=''' 3 mutation deleteobject(\\$id id!){ 4 deletelanguage(input {id \\$id}){ 5 language{ 6 name, 7 id 8 } 9 } 10 } 11 '''; 12 final variable={ 13 "id"\ objectid, 14 }; 15 } en esto, solo requerimos el objectid objectid de la fila que necesita ser eliminada inicializa el graphqlclient graphqlclient y envía la consulta a través de queryoptions() queryoptions() 1 future\<queryresult> deletedata() async{ 2 string delete=''' 3 mutation deleteobject(\\$id id!){ 4 deletelanguage(input {id \\$id}){ 5 language{ 6 name, 7 id 8 } 9 } 10 } 11 '''; 12 final variable={ 13 "id"\ objectid, 14 }; 15 16 graphqlconfiguration configuration = graphqlconfiguration(); 17 graphqlclient client = configuration clienttoquery(); 18 19 queryresult queryresult = await client query( 20 queryoptions(documentnode gql(delete), variables variable), 21 ); 22 23 return queryresult; 24 } en mutationpage mutationpage en el deletedatabuttonpressed deletedatabuttonpressed verifica si el parámetro objectid objectid no está vacío o nulo y llama a la deletedata() deletedata() función reinicie la aplicación , ingrese el objectid de la fila que se va a eliminar y presione el botón eliminar datos debería eliminar una fila específica de su idioma idioma clase éxito , su aplicación finalmente ha realizado sus operaciones de mutación !!! main dart main dart debería verse así 1 import 'package\ back4appgraphqldemo/mutation page dart'; 2 import 'package\ flutter/material dart'; 3 import 'package\ graphql flutter/graphql flutter dart'; 4 import 'consonents dart'; 5 import 'dart\ ui'; 6 7 void main() { 8 runapp(myapp()); 9 } 10 11 class myapp extends statelesswidget { 12 @override 13 widget build(buildcontext context) { 14 final httplink httplink = httplink( 15 uri 'https //parseapi back4app com/graphql', 16 headers { 17 'x parse application id' kparseapplicationid, 18 'x parse client key' kparseclientkey, 19 'x parse master key' kparsemasterkey, 20 //'x parse rest api key' kparserestapikey, 21 }, //getheaders() 22 ); 23 24 valuenotifier\<graphqlclient> client = valuenotifier( 25 graphqlclient( 26 cache optimisticcache(dataidfromobject typenamedataidfromobject), 27 link httplink, 28 ), 29 ); 30 31 return materialapp( 32 home graphqlprovider( 33 child myhomepage(), 34 client client, 35 ), 36 ); 37 } 38 } 39 40 class myhomepage extends statefulwidget { 41 @override 42 myhomepagestate createstate() => myhomepagestate(); 43 } 44 45 class myhomepagestate extends state\<myhomepage> { 46 string name; 47 string saveformat; 48 string objectid; 49 50 string query = ''' 51 query findlanguages{ 52 languages{ 53 count, 54 edges{ 55 node{ 56 name, 57 saveformat 58 } 59 } 60 } 61 } 62 '''; 63 64 @override 65 widget build(buildcontext context) { 66 return safearea( 67 child scaffold( 68 appbar appbar( 69 title text( 70 'parsing data using graphql', 71 ), 72 ), 73 floatingactionbutton row( 74 mainaxisalignment mainaxisalignment end, 75 children \[ 76 floatingactionbutton( 77 herotag 'mutation page', 78 child text('m', 79 style textstyle( 80 color colors white, 81 ), 82 ), 83 onpressed (){ 84 navigator pushreplacement(context, materialpageroute( 85 builder ((context){ 86 return mutationpage(); 87 }) 88 )); 89 }, 90 ), 91 ], 92 ), 93 body query( 94 options queryoptions( 95 documentnode gql(query), 96 ), 97 builder ( 98 queryresult result, { 99 refetch refetch, 100 fetchmore fetchmore, 101 }) { 102 if (result data == null) { 103 return center( 104 child text( 105 "loading ", 106 style textstyle(fontsize 20 0), 107 )); 108 } else { 109 return listview\ builder( 110 itembuilder (buildcontext context, int index) { 111 return listtile( 112 title text(result data\["languages"]\["edges"]\[index]\["node"] 113 \['name']), 114 trailing text(result data\["languages"]\["edges"]\[index] 115 \["node"]\['saveformat']), 116 117 ); 118 }, 119 itemcount result data\["languages"]\["edges"] length, 120 ); 121 } 122 }, 123 ), 124 ), 125 ); 126 } 127 } database utils dart database utils dart debería ser así 1 import 'package\ back4appgraphqldemo/graphql configration dart'; 2 import 'package\ graphql flutter/graphql flutter dart'; 3 4 class databaseutils{ 5 6 final string langname,saveformat,objectid; 7 8 databaseutils({this langname="",this saveformat="",this objectid=""}); 9 10 string delete=''' 11 mutation delete languages(\\$id id!){ 12 deletelanguage(input {id \\$id}){ 13 language{ 14 name, 15 id 16 } 17 } 18 } 19 '''; 20 21 string adddata=''' 22 mutation create languages(\\$input createlanguagefieldsinput){ 23 createlanguage(input {fields \\$input}){ 24 language{ 25 name, 26 saveformat 27 } 28 } 29 } 30 '''; 31 string update=''' 32 mutation update languages(\\$id id!,\\$input updatelanguagefieldsinput){ 33 updatelanguage(input {id \\$id, fields \\$input}){ 34 language{ 35 name, 36 id 37 } 38 } 39 } 40 '''; 41 42 future\<queryresult> senddata() async{ 43 44 final variable ={ 45 "input" { 46 "name" langname, 47 "saveformat" saveformat, 48 } 49 }; 50 print('sendingdata'); 51 52 graphqlconfiguration configuration = graphqlconfiguration(); 53 graphqlclient client = configuration clienttoquery(); 54 55 queryresult queryresult = await client query( 56 queryoptions(documentnode gql(adddata), variables variable), 57 ); 58 return queryresult; 59 60 } 61 future\<queryresult> updatedata() async{ 62 final variable={ 63 "id"\ objectid, 64 "input" { 65 "name" langname 66 } 67 }; 68 69 graphqlconfiguration configuration = graphqlconfiguration(); 70 graphqlclient client = configuration clienttoquery(); 71 72 queryresult queryresult = await client query( 73 queryoptions(documentnode gql(update), variables variable), 74 ); 75 return queryresult; 76 } 77 78 79 future\<queryresult> deletedata() async{ 80 final variable={ 81 "id"\ objectid, 82 }; 83 84 graphqlconfiguration configuration = graphqlconfiguration(); 85 graphqlclient client = configuration clienttoquery(); 86 87 queryresult queryresult = await client query( 88 queryoptions(documentnode gql(delete), variables variable), 89 ); 90 91 return queryresult; 92 } 93 } mutaion page dart mutaion page dart debería verse así 1 import 'package\ back4appgraphqldemo/app ui dart'; 2 import 'package\ back4appgraphqldemo/database utils dart'; 3 import 'package\ flutter/material dart'; 4 5 class mutationpage extends statelesswidget { 6 7 string langname,saveformat,objectid; 8 databaseutils utils; 9 10 @override 11 widget build(buildcontext context) { 12 return appui( 13 onchangedname (text){ 14 langname=text; 15 }, 16 onchangedsaveformat (text){ 17 saveformat=text; 18 }, 19 onchangedobjectid (text){ 20 objectid=text; 21 }, 22 23 senddatabuttonpressed (){ 24 if(langname isnotempty && saveformat isnotempty){ 25 utils = databaseutils( 26 langname langname, 27 saveformat saveformat , 28 ); 29 utils senddata(); 30 } 31 }, 32 deletedatabuttonpressed (){ 33 if(objectid isnotempty){ 34 utils = databaseutils( 35 objectid objectid, 36 ); 37 utils deletedata(); 38 } 39 }, 40 updatebuttonpressed (){ 41 if(langname isnotempty && saveformat isnotempty && objectid isnotempty){ 42 utils = databaseutils( 43 langname langname, 44 saveformat saveformat , 45 objectid objectid 46 ); 47 utils updatedata(); 48 } 49 }, 50 ); 51 } 52 } conclusión en esta guía utilizamos mutaciones de graphql en la aplicación flutter para crear nuevos objetos en back4app; actualizar objetos en back4app; eliminar objetos en back4app en este punto tienes un proyecto crud de flutter graphql completamente funcional donde puedes usar como punto de partida para desarrollar tu próxima aplicación en la próxima guía vamos a profundizar en las consultas mostrando cómo hacerlas para recuperar datos de back4app y mostrarlos en nuestra aplicación flutter ¡que tengas un gran día!