<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Fajar Muhamad</title>
    <description>The latest articles on DEV Community by Fajar Muhamad (@alafajar).</description>
    <link>https://dev.to/alafajar</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1005178%2Fd15ff398-d7dd-4bd9-b466-6b207392a111.jpeg</url>
      <title>DEV Community: Fajar Muhamad</title>
      <link>https://dev.to/alafajar</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/alafajar"/>
    <language>en</language>
    <item>
      <title>Reusable Input: Penambahan Props Yang Dibutuhkan (Bag. 2)</title>
      <dc:creator>Fajar Muhamad</dc:creator>
      <pubDate>Sun, 15 Jun 2025 05:50:08 +0000</pubDate>
      <link>https://dev.to/alafajar/reusable-input-penambahan-props-yang-dibutuhkan-bag-2-mfn</link>
      <guid>https://dev.to/alafajar/reusable-input-penambahan-props-yang-dibutuhkan-bag-2-mfn</guid>
      <description>&lt;p&gt;Melanjutkan pembuatan reusable input yang telah dilakukan &lt;a href="https://dev.to/alafajar/reusable-input-dari-yang-sederhana-dulu-bagian-1-33g5"&gt;sebelumnya&lt;/a&gt;, kali ini akan menambahkan untuk props validation dan accessibility.&lt;/p&gt;

&lt;h2&gt;
  
  
  Perbaikan Props Validation
&lt;/h2&gt;

&lt;p&gt;jika ingin menggunakan reusable component input perlu dibutuhkan props validation agar component itu tidak keluar dari aturan yang di inginkan.&lt;/p&gt;

&lt;p&gt;Pada komponent input ini, kita menginginkan komponen yang menghasilkan nilai string,tanpa berlama-lama tambahkan depedency prop-types jika menggunakan react javascript.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npm run prop-types&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;setelah install package, import prop-types pada komponen input yang digunakan&lt;/p&gt;

&lt;p&gt;&lt;code&gt;import PropTypes from "prop-types";&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;lalu pada bagian penggunaan prop-types tambahkan setelah deklarasi komponen&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Input.propTypes = {
  onChange: PropTypes.func.isRequired,
  placeholder: PropTypes.string,
  value: PropTypes.string,
  label: PropTypes.string.isRequired,
  type: PropTypes.string,
  required: PropTypes.bool,
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Penjelasan: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Input pemanggilan komponen yang digunakan&lt;/li&gt;
&lt;li&gt;propTypes deklarasi penggunaan fungsi pada komponen&lt;/li&gt;
&lt;li&gt;nilai {} untuk propTypes berupa object, membatasi tipe data yang akan digunakan&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Perbaikan Accessibility
&lt;/h2&gt;

&lt;p&gt;pada bagian accessibility ini, kita menambahkan &lt;code&gt;id&lt;/code&gt; pada props input&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Input.propTypes = {
  onChange: PropTypes.func.isRequired,
  placeholder: PropTypes.string,
  value: PropTypes.string,
  label: PropTypes.string.isRequired,
  type: PropTypes.string,
  required: PropTypes.bool,
  id: PropsTypes.string
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;lalu pada komponen jsx untuk label menjadi seperti ini&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;label
  htmlFor="input"
  className="col-span-1 font-bold text-base capitalize text-gray-700"&amp;gt;
   {label}
   {required &amp;amp;&amp;amp; (
     &amp;lt;span className="text-red-500 ml-1" aria-label="required"&amp;gt;*&amp;lt;/span&amp;gt;
   )}
&amp;lt;/label&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Penambahan:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;htmlFor kegunaan untuk mengikat tag label pada elemen tertentu (input)&lt;/li&gt;
&lt;li&gt;aria-label kegunaan untuk menyediakan keterangan pada fitur di web browser untuk pengguna berkebutuhan khusus
bisa cek &lt;a href="https://www.a11y-collective.com/blog/aria-labels/" rel="noopener noreferrer"&gt;di sini&lt;/a&gt; untuk lengkapnya penggunaan atribut aria&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;selanjutnya pada bagian tag input&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; &amp;lt;input
  id="input"
  value={value ?? ""}
  onChange={(event) =&amp;gt; onChange(event.target.value)}
  type={type}
  className="col-span-3 bg-white w-full px-4 py-2 text-base font-medium text-gray-700 rounded-md transition-colors duration-200 border-gray-300 outline-none border-2 focus:border-pink-400 focus:ring-2 focus:ring-pink-100"
  placeholder={placeholder}
  required={required}
  aria-required={required}
/&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;untuk kenyamanan id dan htmlFor tidak akan digunakan secara hard code, tetapi kita akan memberikan kondisi agar tetap responsif, tambahkan baris ini sebelum return jsx&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  const inputId = id || `input-${label?.toLowerCase().replace(/\s+/g, "-")}`;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;dan full code akan terlihat seperti ini&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Input.jsx - Perbaikan tahap 2
import PropTypes from "prop-types";

const Input = (props) =&amp;gt; {
  const {
    onChange,
    placeholder,
    value,
    label,
    type = "text",
    required = false,
    id,
  } = props;

  const inputId = id || `input-${label?.toLowerCase().replace(/\s+/g, "-")}`;

  return (
    &amp;lt;div className="grid grid-cols-4 gap-4 items-center w-full"&amp;gt;
      &amp;lt;label
        htmlFor={inputId}
        className="col-span-1 font-bold text-base capitalize text-gray-700"
      &amp;gt;
        {label}
        {required &amp;amp;&amp;amp; (
          &amp;lt;span className="text-red-500 ml-1" aria-label="required"&amp;gt;
            *
          &amp;lt;/span&amp;gt;
        )}
      &amp;lt;/label&amp;gt;
      &amp;lt;input
        id={inputId}
        value={value ?? ""}
        onChange={(event) =&amp;gt; onChange(event.target.value)}
        type={type}
        className="col-span-3 bg-white w-full px-4 py-2 text-base font-medium text-gray-700 rounded-md transition-colors duration-200 border-gray-300 outline-none border-2 focus:border-pink-400 focus:ring-2 focus:ring-pink-100"
        placeholder={placeholder}
        required={required}
        aria-required={required}
      /&amp;gt;
    &amp;lt;/div&amp;gt;
  );
};

// ✅ Props validation
Input.propTypes = {
  onChange: PropTypes.func.isRequired,
  placeholder: PropTypes.string,
  value: PropTypes.string,
  label: PropTypes.string.isRequired,
  type: PropTypes.string,
  required: PropTypes.bool,
  id: PropTypes.string,
};

export default Input;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;dan hasil akhir akan tampak seperti ini:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F45j03jwrj7tg845zbkvh.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F45j03jwrj7tg845zbkvh.gif" alt="Hasil akhir tutorial 2" width="582" height="92"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Terima kasih sudah membaca, rispek guys 🫡&lt;/p&gt;

&lt;p&gt;untuk link github: &lt;a href="https://github.com/alafajar/learn-build-component" rel="noopener noreferrer"&gt;disini&lt;/a&gt;&lt;/p&gt;

</description>
      <category>learning</category>
      <category>webdev</category>
      <category>react</category>
      <category>webcomponents</category>
    </item>
    <item>
      <title>Reusable Input: Dari Yang Sederhana Dulu (Bagian 1)</title>
      <dc:creator>Fajar Muhamad</dc:creator>
      <pubDate>Sat, 24 May 2025 06:45:39 +0000</pubDate>
      <link>https://dev.to/alafajar/reusable-input-dari-yang-sederhana-dulu-bagian-1-33g5</link>
      <guid>https://dev.to/alafajar/reusable-input-dari-yang-sederhana-dulu-bagian-1-33g5</guid>
      <description>&lt;p&gt;Halo semuanya, sebagai reactjs developer saya ingin sharing tentang permasalahan yang menjadi benak saya untuk memulai suatu projek.&lt;/p&gt;

&lt;p&gt;Pada dasarnya, sering kali setiap menjalankan projek, saya pribadi menggunakan library tambahan untuk komponen yang ingin digunakan.&lt;/p&gt;

&lt;p&gt;Kali ini saya ingin mengeksplor diri saya dengan membuat komponen itu sendiri, dan semaksimal mungkin tidak menambahkan depedensi lain.&lt;/p&gt;

&lt;h2&gt;
  
  
  Hal Pertama, Input Komponen Yang Akan Digunakan
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe4x3k5z13dnl7njhuu74.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe4x3k5z13dnl7njhuu74.png" alt="Contoh design input yang ingin digunakan" width="800" height="124"&gt;&lt;/a&gt;&lt;/p&gt;
Contoh design input yang ingin digunakan



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fygilj8bwn3rm1ogk76hq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fygilj8bwn3rm1ogk76hq.png" alt="Pembagian kolom" width="800" height="98"&gt;&lt;/a&gt;&lt;/p&gt;
Pembagian kolom



&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Disclaimer! Pada pembuatan ini tidak mengacu pada pixel perfect desain&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;dari gambar diatas dapat kita bedah:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Komponen tersebut akan terdapat properti untuk required&lt;/li&gt;
&lt;li&gt;Terdapat 2 kolom, untuk menampilkan label, dan komponen input&lt;/li&gt;
&lt;li&gt;Terdapat rounded border, padding, font style, outline saat hover&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Mari Kita Buat!
&lt;/h2&gt;

&lt;p&gt;instal dahulu agar dapat menggunakan react, saya menggunakan react-vite untuk pilihan bebas yang penting react 😅.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npm create vite . -- --templte react~&lt;/code&gt;&lt;br&gt;
&lt;a href="https://react.dev/learn/creating-a-react-app" rel="noopener noreferrer"&gt;bisa kalian cek di sini&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;setelah itu mari membuat komponen Input.jsx dengan sederhana dahulu&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;//component Input.jsx
const Input = (props) =&amp;gt; {
  const {
    onChange,
    placeholder,
    value,
    label,
    type = "text",
    required = false,
  } = props;
  return (
    &amp;lt;div&amp;gt;
      &amp;lt;label&amp;gt;
        {label}
        &amp;lt;span&amp;gt;{required &amp;amp;&amp;amp; "*"}&amp;lt;/span&amp;gt;
      &amp;lt;/label&amp;gt;
      &amp;lt;input
        value={value ?? ""}
        onChange={(event) =&amp;gt; onChange(event.target.value)}
        type={type}
        placeholder={placeholder}
        required={required}
      /&amp;gt;
    &amp;lt;/div&amp;gt;
  );
};

export default Input;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;lalu pada pemakaian di parent komponen&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;//Parent Component
import { useState } from "react";
import "./App.css";
import Input from "./Input";

function App() {
  const [value, setValue] = useState("");
  const InputChange = (val) =&amp;gt; {
    setValue(val);
  };

  return (
    &amp;lt;&amp;gt;
      &amp;lt;Input
        value={value}
        label="nama"
        placeholder="Type name here..."
        onChange={InputChange}
        required
      /&amp;gt;
    &amp;lt;/&amp;gt;
  );
}

export default App;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fctpw6bqpp8zip0h8ojn0.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fctpw6bqpp8zip0h8ojn0.gif" alt="Hasil input sederhana" width="476" height="94"&gt;&lt;/a&gt;&lt;/p&gt;
Hasil Input sederhana



&lt;h2&gt;
  
  
  Melakukan Styling Pada Komponen
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;//component Input.jsx
const Input = (props) =&amp;gt; {
  const {
    onChange,
    placeholder,
    value,
    label,
    type = "text",
    required = false,
  } = props;
  return (
    &amp;lt;div className="grid grid-cols-4 gap-1 items-center w-full"&amp;gt;
      &amp;lt;label className="col-span-1 font-bold text-base capitalize text-gray-600"&amp;gt;
        {label}
        &amp;lt;span&amp;gt;{required &amp;amp;&amp;amp; "*"}&amp;lt;/span&amp;gt;
      &amp;lt;/label&amp;gt;
      &amp;lt;input
        value={value ?? ""}
        onChange={(event) =&amp;gt; onChange(event.target.value)}
        type={type}
        className="col-span-3 bg-white w-full px-4 py-2 text-base font-medium text-gray-600 rounded-md transition-colors duration-200 border-gray-300 outline-none border-2 focus:border-pink-400"
        placeholder={placeholder}
        required={required}
      /&amp;gt;
    &amp;lt;/div&amp;gt;
  );
};

export default Input;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fatxs4s90yaksci4bdf5h.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fatxs4s90yaksci4bdf5h.gif" alt="Input styling" width="718" height="94"&gt;&lt;/a&gt;&lt;/p&gt;
Komponen input setelah styling



&lt;p&gt;&lt;br&gt;&lt;br&gt;
Terima kasih sudah membaca! 🫡 Rispek guys!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/alafajar/learn-build-component" rel="noopener noreferrer"&gt;github/learn-build/component&lt;/a&gt;&lt;/p&gt;

</description>
      <category>learning</category>
      <category>webcomponents</category>
      <category>react</category>
    </item>
  </channel>
</rss>
