We are using graphql and relay, and recompose.
I am getting some data from a Unit, but I also need some data from its Project.(A unit belongs to a project)
And I have figured out how to, get some images i need from the project like so:
project {
images {
fileKey
aspectRatio
}
but i get many images.. like 20.. and i just need the first one.. How do i tell relay or graphQl to give me just one?
Thanks, here is my whole fragment:
const enhance = compose(
fragment(graphql`
fragment DetailsSectionContainer_unit on Unit {
tourIdArchilogic
tourIdMatterport
images {
fileKey
aspectRatio
}
...TitleRowContainer_unit
...UnitSummaryContainer_unit
...ContactFormColumnContainer_unit
project {
images {
fileKey
aspectRatio
}
...ContactFormColumnContainer_project
}
company {
...ContactFormColumnContainer_company
}
...TourContainer_unit
}
fragment DetailsSectionContainer_rentedUnit on RentedUnit {
...UnitSummaryContainer_rentedUnit
}
fragment DetailsSectionContainer_vacantUnit on VacantUnit {
...UnitSummaryContainer_vacantUnit
}
`),
);
you should change the return type of your images to a connection, then you tell the server how many images you want to fetch like this:
project {
images(first: 1) {
edges {
node {
fileKey
aspectRatio
}
}
}
}
More about connections here ->
Grahpql connections
Related
I have a query:
query {
productByHandle(handle: "${productHandle}") {
variants(first: 3) {
edges {
node {
title
id
priceV2 {
amount
}
image {
transformedSrc(maxWidth: 400)
}
}
}
}
}
}
Which works great. However, I'm struggling to find the syntax to get multiple transformedSrcs from the variant image. I want to use this for an image srcset, so I'll need to have multiple sizes returned.
I'm new to GraphQL in general. I tried an array on the image, using an AND with multiple maxWidth and scale, duplicating the image piece, etc. I've also searched the Shopify API docs many times.
Is this just not possible for some reason, or am I missing something?
I'm also curious for answers and new to GraphQL. I seem to have had some success using aliases of transformedSrc in the query, see below. Not entirely sure if this is the correct way though. I'm surprised by the lack of info consider it's essential for fast loading sites.
query {
collectionByHandle(handle: "archived") {
products(first: 250) {
edges {
node {
id
title
description
tags
images(first: 100) {
edges {
node {
altText
originalSrc
smallImage: transformedSrc(maxWidth: 200, crop: CENTER)
bigImage: transformedSrc(maxWidth: 400, crop: CENTER)
}
}
}
}
}
}
}
}
I've only really just started on Tornadofx and was having a bit of trouble trying to figure out how to reload a view so the controls in that view are refreshed.
Below is a simplified version of the code I'm working with. I've got a loop to generate radio-button controls based on strings in a list.
class MainView: View("MainView") {
override val root = vbox {
for(x in radioText) {
radiobutton(x, radioGroup) {
action {
radioSelected = this#radiobutton.text
}
}
}
button("Next") {
action {
// Reload View to update radiobuttons with new values
}
}
}
}
In the program I need to go through several sets of these radio buttons, and so the idea was that each time the user presses the "Next" button, the items in the radioText list would be updated to match the next set of radio-buttons. Then I was looking for a way to get the view to update with these new values.
I tried using openWindow() to open a new instance of the view, but then when I used close() to get rid of the previous instance and ended up closing both windows.
button("Next") {
action {
MainView().openWindow()
close()
}
}
Any help with this would be much appreciated,
Thanks.
If I understood correctly, you are trying to have a list of string and generate radiobuttons with it. So, by adding the variables to your example, would be something like this:
class MainView: View("MainView") {
val radioText = ArrayList<String>()
var radioGroup : ToggleGroup by singleAssign()
lateinit var radioSelected : String
override val root = vbox {
radioText.addAll(arrayListOf("One","Two","Three","Four"))
radioGroup = togglegroup(){}
for(x in radioText) {
radiobutton(x,radioGroup) {
action {
radioSelected = text //You don't need this#radiobutton.text
}
}
}
button("Next") {
action {
// Reload View to update radiobuttons with new values
}
}
}
}
I thing is a better idea having your radiobutton created by a listview, wich would be updated by a observable list of string, like I do bellow:
class MainView2: View("MainView") {
// this is a list of observable string, so when the items on his list change
// the listview is updated
val radioText = FXCollections.observableArrayList<String>()
var radioGroup : ToggleGroup by singleAssign()
lateinit var radioSelected : String
override val root = vbox() {
prefWidth = 200.0
prefHeight = 300.0
radioText.setAll("One","Two","Three","Four")
radioGroup = togglegroup(){}
listview<String>(radioText){
// Setting listview height dinamically
fixedCellSize = 25.0
prefHeightProperty().bind(radioText.sizeProperty.multiply(fixedCellSizeProperty().add(2)))
// Generating the radiobutton acording to strings on radioText
cellFormat {
graphic = cache(it){
radiobutton(it,radioGroup){
action {
radioSelected = text
}
}
}
}
}
button("Next") {
action {
radioText.clear()
radioText.setAll("Five","Six","Seven","Eight","Nine","Ten")
}
}
}
}
Please let me know if there is something you don't understand on my aproach.
I currently have images which the image name is returned by a function and is dynamically called based on a variable like this:
String _setImage() {
if (currentQuestion > 1 && currentQuestion < 11) {
return "assets/images/image_$intensityIndex.png";
} else {
return "assets/images/image.png";
}
}
I want to switch to preloading the images and I am using the technique described at Preload images in a stateful widget on Flutter, but I am not sure how to have the function return an image which the name is dynamically determined based on another variable. Here is what I have so far:
void initState() {
super.initState();
image0 = Image.asset('assets/images/image_0.png');
image1 = Image.asset('assets/images/image_1.png');
image2 = Image.asset('assets/images/image_2.png');
image3 = Image.asset('assets/images/image_3.png');
}
void didChangeDependencies() {
super.didChangeDependencies();
precacheImage(image0.image, context);
precacheImage(image1.image, context);
precacheImage(image2.image, context);
precacheImage(image3.image, context);
}
Image _setImage() {
if (currentQuestion > 1 && currentQuestion < 11) {
return ______________;
} else {
return image0;
}
}
All help is appreciated!
Am not sure how to return an image which the name is dynamically
determined based on another variable
You don't need to return with precach because if you use exact image that you cache.
Ex:
precacheImage('assets/images/image_1.png'); // if this is the image name
Image.asset('assets/images/image_1.png'); // when you use this it is getting from the cache but the path should be same.
If I explain it another way:
precacheImage("assets/images/image_$intensityIndex.png"); // image_1.png
Image.asset('assets/images/image_1.png'); // when you do this, asset taking from the cache by looking at the path.
Anywhere in a NavHostFragment I can do findNavController().navigateUp()
Or, if in my Fragment I have a button to be used for navigation, I could do either:
editButton.setOnClickListener { v ->
v.findNavController().navigateUp()
}
or
editButton.setOnClickListener {
findNavController().navigateUp()
}
Why would I use one extension function vs the other when setting up a button click listener in a Fragment?
They are almost the same, Fragment.findNavController() is just a handy shortcut, it actually calls Navigation.findNavController(view) at the end. Both of them are getting the NavController from the root view of the fragment.
// NavHostFragment.java
public static NavController findNavController(#NonNull Fragment fragment) {
....
View view = fragment.getView();
if (view != null) {
return Navigation.findNavController(view);
}
...
}
Thank you for the Java answer, I offer a ViewBinding solution in kotlin, doing the same
// NavHostFragment.kotlin
fun findMyNavController(#NonNull fragment: Fragment): NavController {
return Navigation.findNavController(binding.root)
}
Although they are not identical as suggested by the top voted answer, the performance difference should be negligible in general scenarios. However if you use the v.findNavController() on a View which is deeply nested down, then you should prefer Fragment extension findNavController() as it will perform better.
In general I don't see any reason to prefer the v.findNavController over the Fragment extension. following is the complete code of this method from NavHostFragment and it only calls Navigation.findNavController if it doesn't find the NavController using the fragment
public static NavController findNavController(#NonNull Fragment fragment) {
Fragment findFragment = fragment;
while (findFragment != null) {
if (findFragment instanceof NavHostFragment) {
return ((NavHostFragment) findFragment).getNavController();
}
Fragment primaryNavFragment = findFragment.requireFragmentManager()
.getPrimaryNavigationFragment();
if (primaryNavFragment instanceof NavHostFragment) {
return ((NavHostFragment) primaryNavFragment).getNavController();
}
findFragment = findFragment.getParentFragment();
}
// Try looking for one associated with the view instead, if applicable
View view = fragment.getView();
if (view != null) {
return Navigation.findNavController(view);
}
throw new IllegalStateException("Fragment " + fragment
+ " does not have a NavController set");
}
i have a custom saga, which responds to a simple search user action, if it finds a single user, it should show it otherwise go to the user list.
Problem is that when i push the new route, i can see that state changes but the app is not rendering the new route. I looked through the source and cant find any update-blockers.
If i do the push action twice, for some reason, only causing the location key to change again, the app re-renders correctly. Don't know where to keep looking, so any ideas of what the problem is?
import { put, takeEvery, all, call } from "redux-saga/effects";
import { searchUser } from "../services/userService";
import { SEARCH_USER } from "../actions/searchUser";
import { showNotification } from "admin-on-rest";
import { push, replace } from "react-router-redux";
function* handleSearchUser(action) {
try {
const { searchParam } = action.payload;
const filter = {};
if (isNaN(searchParam)) {
filter.Email = searchParam;
} else {
filter.UserId = parseInt(searchParam);
}
const result = yield call(searchUser, 0, 25, filter);
if (result && result.length === 1) {
// Duplicate this row and the page re-renders the correct page
yield put(push(`/User/${result[0].UserId}/show`));
} else {
yield put(
push(
`/User?filter=${JSON.stringify(
filter
)}&order=DESC&sort=id&page=1&perPage=25`
)
);
}
} catch (error) {
console.error(error);
yield put(showNotification("Error: error when searching", "warning"));
}
}
export default function* searchUserSaga() {
yield all([takeEvery(SEARCH_USER, handleSearchUser)]);
}
Was using gatsbyjs. I switched to Create React App for building and all problems went away.