/ Gists

Gists

On gists

Promises, Await / Async, Callbacks

JavaScript

demo1.html #

<!--https://www.loginradius.com/blog/engineering/callback-vs-promises-vs-async-await/-->

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>Document</title>
    </head>
    <body>
        <script type="module">
            // 1 Promises - way 1

            // Promise1
            const promise1 = new Promise((resolve, reject) => {
                const condition = true;
                if (condition) {
                    setTimeout(function () {
                        resolve('Promise is resolved!'); // fulfilled
                    }, 300);
                } else {
                    reject('Promise is rejected!');
                }
            });

            // Promise2
            const promise2 = function () {
                return new Promise(function (resolve, reject) {
                    const message = `Hi, How are you!`;

                    resolve(message);
                });
            };

            // Test = chaining
            const testPromise = function () {
                promise1
                    .then(promise2)
                    .then(successMsg => {
                        console.log('Success:' + successMsg);
                    })
                    .catch(errorMsg => {
                        console.log('Error:' + errorMsg);
                    });
            };

            testPromise();

            // 2 Async / Await  = way 2
            async function testPromise2() {
                try {
                    let message = await promise1;
                    let message2 = await promise2();
                    console.log(message);
                    console.log(message2);
                } catch (error) {
                    console.log('Error:' + error.message);
                }
            }

            // we call it ...
            (async () => {
                await testPromise2();
            })();
        </script>
    </body>
</html>

On gists

Multi-file single-file components (external files)

Vue.js

vuecomp.vue #

<!-- A "single" file component -->
<template src="./template.html"></template>
<script src="./script.js"></script>
<style scoped src="./styles.css"></style>

On gists

How to make a variable created outside of Vue reactive - Options API

Vue.js

example.js #

// options API

const externalVariable = getValue();

export default {
  data() {
    return {
      reactiveVariable: externalVariable,
    };
  }
};


On gists

Composable: useMouse

Vue.js

useMouse.js #

import { ref, onMounted, onUnmounted } from 'vue'
export function useMouse() {
  const x = ref(0)
  const y = ref(0)
  function update(event) {
    x.value = event.pageX
    y.value = event.pageY
  }
  onMounted(() => window.addEventListener('mousemove', update))
  onUnmounted(() => window.removeEventListener('mousemove', update))
  return { x, y }
}



// usage
<template>
  X: {{ x }} Y: {{ y }}
</template>
<script setup>
  import { useMouse } from './useMouse';
  const { x, y } = useMouse();
</script>


// with params = config
// Using an options object
const title = useTitle('A new title', { titleTemplate: '>> %s <<' });

// or with many params
const title = useTitle('A new title', '>> %s <<');


export function useMouse(options) {
  const {
    asArray = false,
    throttle = false,
  } = options;
  // ...
};

On gists

Ajax / Fetch()

JavaScript

examples.js #

/**
 * Fetch
 * 
 * RESTFul API - https://jsonplaceholder.typicode.com/
 * Docs - https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch
 */

fetch('https://jsonplaceholder.typicode.com/comments/1')
    .then(response => response.json())
    .then(data => console.log(data))

fetch('https://jsonplaceholder.typicode.com/comments', {
        method: "POST",
        body: JSON.stringify({
            postId: 1,
            name: 'Dylan',
            email: 'dylansemail310@gmail.com',
            body: 'That was dope!'
        })
    })
    .then(response => response.json())
    .then(data => console.log(data))
    
    
    
    /*
    examples
    */
    
  fetch('https://api.example.com/items')
  .then(res => res.json())
  .then(data => {
    console.log(data) 
  })
  .catch(err => {
    console.log('Error:', err)
  })
  

// POST  
const body = {title: 'Foo', body: 'Bar'};

fetch('https://api.example.com/items', {
  method: 'POST', 
  headers: {
    'Content-Type': 'application/json'
  },
  body: JSON.stringify(body)
})
  .then(res => res.json())
  .then(data => console.log(data))
  .catch(err => console.log(err))
  
  
  
// FILE UPLOAD
const formData = new FormData();
formData.append('file', fileInput.files[0]);

fetch('https://api.example.com/upload', {
  method: 'POST',
  body: formData
});


// With Async/Await
async function fetchData() {
  try {
    const response = await fetch('https://api.example.com/items');
    const data = await response.json();
    console.log(data);
  } catch(err) {
    console.log('Error:', err);
  }
}

fetchData();


// Fetching From Multiple Sources
async function get() {

  const [userRes, postsRes] = await Promise.all([
    fetch('/user'),
    fetch('/posts')
  ]);
  
  const user = await userRes.json();
  const posts = await postsRes.json();

  return {user, posts};

}

const data = await get();


// ERRORS
fetch('https://api.example.com/items')
  .then(res => {
    // Handle response
  })
  .catch(err => {
    console.log('Fetch Error :-S', err);  
  });
  
  
  fetch('https://api.example.com/items')
  .then(res => {
    if (!res.ok) {
      throw new Error('Bad status code'); 
    }
   
    return res.json()
  })
  .then(data => {
    console.log(data); 
  })
  .catch(err => {
    console.log('Error:', err); 
  });
  
  
  
  
  // full config with cors and auth

  fetch('https://api.example.com/users', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Authorization': 'Bearer token123'
  },
  body: JSON.stringify({ name: 'Alice', age: 25 }),
  mode: 'cors',
  cache: 'no-cache',
  credentials: 'same-origin'
});





//  Built-In Request Abortion Mechanism
const controller = new AbortController();
const signal = controller.signal;

fetch('https://api.example.com/data', { signal })
  .then(response => response.json())
  .then(data => console.log(data))
  .catch(error => {
    if (error.name === 'AbortError') {
      console.log('Request was cancelled');
    } else {
      console.error('Request failed:', error);
    }
  });
// Cancel the request after 3 seconds
setTimeout(() => controller.abort(), 3000);





// Improved Error Handling
fetch('https://api.example.com/data')
  .then(response => {
    if (!response.ok) {
      throw new Error(`HTTP error! Status: ${response.status}`);
    }
    return response.json();
  })
  .then(data => console.log('Success:', data))
  .catch(error => console.error('Error:', error));

On gists

SelectionResolver

Nette PHP Nette-Database PHP Patterns

SelectionResolver.php #

<?php

// usage
		$this->paymentList = $this->payment->getPaymentSelectionResolver()
				->getBaseSelection()
				//->setCountry($this->order->billing__country_id)
				->setUserGroups($this->user->isLoggedIn() ? $this->user->getRoles() : NULL)
				->setOnlyForProduct($this->payment->getPaymentOnlyForProduct($this->order->getItems($this->order::ITEM_PRODUCT)))
				->toArray();
				
// ...				
    public function getPaymentSelectionResolver()
    {
        return $this->paymentSelectionResolver;
    }
    
    
// ...
class PaymentEshopOrderSelectionResolver
{
    /**
     * @var Context
     */
    protected $connection;

    /**
     * 
     * @var Nette\Database\Table\Selection
     */
    protected $selection;


    public function __construct(Context $connection)
    {
        $this->connection = $connection;
    }

    
    public function getBaseSelection()
    {
        $this->selection = $this->connection->table('payment_type')
            ->where('active = 1');
        return $this;
    }


    public function setCountry($countryId)
    {
        $this->selection->where(':payment_type_country.country_id IN (?) OR all_countries = 1', (array) $countryId);
        //$this->selection->where(':transport_type_variant.country_id IS NULL OR :transport_type_variant.country_id IN (?)', (array) $countryId);
        return $this;
    }


    public function setOnlyForProduct($paymentTypeIds = NULL)
    {
        if ($paymentTypeIds === NULL)
        {
            $this->selection->where('only_for_product = 0 OR only_for_product IS NULL');
        }
        else
        {
            $this->selection->where('payment_type.id IN (?)', (array) $paymentTypeIds);
        }
        return $this;
    }


    public function setUserGroups($usegroupsId = NULL)
    {
        if ($usegroupsId === NULL)
        {
            $this->selection->where(':payment_type_usergroup.usergroup_id IS NULL');
        }
        else
        {
            $this->selection->where(':payment_type_usergroup.usergroup_id IS NULL OR :payment_type_usergroup.usergroup_id  IN (?)', $usegroupsId);
        }
        return $this;
    }


    public function toArray()
    {
        $rows = [];
        foreach ($this->selection as $row)
        {
            $rows[$row->id] = $row;
        }

        return $rows;
    }

}

On gists

Click to (fake click aka teleport link)

Vue.js

clickTo.js #

const redirect = target => {
  document.querySelector(target).click()
}

export default {
  install(Vue) {
    Vue.directive('click-to', {
      mounted: function (el, binding) {
        el._clickRedirectCallback = () => redirect(binding.value)
        el.addEventListener('click', el._clickRedirectCallback)
      },
      unmounted: function (el) {
        el.removeEventListener('click', el._clickRedirectCallback)
      }
    })
  }
}

On gists

Composition examples & ways

Vue.js

examples.js #

<template>
    <div>
        <p>Spaces Left: {{ spacesLeft }} out of {{ capacity }}</p>
        <h2>Attending</h2>
        <ul>
            <li v-for="(name, index) in attending" :key="index">
                {{ name }}
            </li>
        </ul>
        <button @click="increaseCapacity()">Increase Capacity</button>
    </div>
</template>
<script>
import { ref, computed } from 'vue';
export default {
    setup() {
        const capacity = ref(4);
        const attending = ref(['Tim', 'Bob', 'Joe']);
        const spacesLeft = computed(() => {
            return capacity.value - attending.value.length;
        });
        function increaseCapacity() {
            capacity.value++;
        }
        return { capacity, attending, spacesLeft, increaseCapacity };
    },
};
</script>


// can be rewritten as:
import {
    reactive,
    computed,
    toRefs
} from "vue";

export default {
    setup() {
        const event = reactive({
            capacity: 4,
            attending: ["Tim", "Bob", "Joe"],
            spacesLeft: computed(() => {
                return event.capacity - event.attending.length;
            })
        });

        function increaseCapacity() {
            event.capacity++;
        }
        return {
            ...toRefs(event),
            increaseCapacity
        };
    }
};


// TO ORGANIZE BY FEATURE
<template>…</template>
<script>
export default {
    setup() {
        const productSearch = useSearch();
        const resultSorting = useSorting({});
        return { productSearch, resultSorting };
    },
};

function useSearch(getResults) {}
function useSorting({ input, options }) {}
</script>


// TO EXTRACT SHARED CODE:
<template>…</template>
<script>
import useSearch from '@use/search';
import useSorting from '@use/sorting';
export default {
    setup() {
        const productSearch = useSearch();
        const resultSorting = useSorting({});
        return { productSearch, resultSorting };
    },
};
</script>

// use/search.js 
export default function useSearch (getResults) { }

// use/sorting.js 
export default function useSorting ({ input, options }) { }

On gists

Composable - replacement for VUEX

Vue.js

example.js #

// https://medium.com/js-dojo/should-you-use-composition-api-as-a-replacement-for-vuex-274356443ebc

// src/global.js
import { reactive, readonly } from "vue";
const state = reactive({
  count: 0
});
const increment = function () {
  state.count++;
}
export default { state: readonly(state), increment };

// src/main.js
import { createApp } from "vue";
import global from "@/global";
const app = createApp({
  provide: {
    global
  },
}

// someComponent.vue
<template>
  <div>{{ global.state.count }}
  <button @click="global.increment">Increment</button>
</template>
<script>
export default {
  inject: ["global"]
}
</script>

On gists

VUEX store in latte template

Vue.js AW

some.latte #

$store.state.modalForm.formId
$store.dispatch('modalForm/close')


  <a 
    @click="$store.dispatch('modalForm/open', { 
        formId: {$data->button__contact_form_section->contact_form_control_id}, 
        sectionId: {$data->button__contact_form_section_id} 
    })"
    class="Btn Btn--Primary cursor-pointer">
    {$data->button_text}
</a>